애벌레 게임(Moving Bug)
1. 프로젝트 개요
이번 프로젝트인 애벌레 게임의 기본 베이스는 1970년대에 출시 된 게임으로 영어로는 Snake game, 일본어로는 ヘビゲーム이라 부른다.
플레이어는 화면에 있는 뱀 (우리 프로그램에서는 애벌레)을 방향키로 조작하여 상하좌우로 움직일 수 있다.
이때 타이머로 AUTO key를 조절하며 1P는 (↑, ↓, ←, → )로, 2P는 ( W, S, A, D )로 방향을 조절 할 수 있다.
애벌레가 먹이를 먹을 때 마다 꼬리의 개수가 증가하며 머리와 꼬리가 부딪혔을 때 Game Over! 창이 출력되면서 게임이 종료된다.
2. 설계작품 개요
2.1. 프로그램 기획
- 애벌레 게임의 기본 베이스는 1970년대에 출시 된 게임으로 영어로는 Snake game, 일본어로는 ヘビゲーム(뱀 게임)라고 부른다.
- 플레이어는 화면에 있는 뱀(처럼 생긴 길쭉한 막대)(우리 프로그램에서는 애벌레)을 방향 키로 조작해서 상하좌우로 움직일 수 있다.
- 애벌레의 머리가 꼬리에 닿으면 죽으면서 게임이 종료된다.
2.2 기본 프로그램 기능
- 방향키
- 1P는 (↑, ↓, ←, →)로 방향 조절한다.
- 2P는 (W, S, A, D)로 방향 조절한다.
- 타이머로 AUTO로 Key 조절한다.
- 먹이를 먹을 때 마다 꼬리의 개수가 증가한다.
- 머리와 꼬리가 부딪혔을 때 Game Over! 창이 출력되고 게임이 종료된다.
3. 설계작품 일정
- 5/24: 애벌레 코드 분석 및 조건 내용 파악
- 5/27 ~ 6/13: 조건에 맞춘 애벌레 게임 프로그램 구현
- 6/13: 최종 보고서 작성 및 제출
- 6/18: 최종 보고서 및 발표
4. 설계 구성요소
4.1. 목표설정(Objective Establishment)
- 경기장은 33*33 크기로 변경, 먹이도 30개로 변경한다.
- 시작하면 애벌레 두 마리(왼쪽 상단에 하나, 오른쪽 하단에 하나) 출력한다.
- 오른쪽 애벌레는 방향키로 이동한다.
- 왼쪽 애벌레는 A(<-) S(위쪽) D(->) W(아래쪽) 으로 이동한다.
- 먹이를 먹으면 먹이는 사라지고 애벌레 꼬리가 생긴다.
- 타이머가 작동하면 애벌레는 계속 움직인다.
- 벽은 통과 못한다.
- 애벌레의 자기 꼬리는 통과 못한다.
- 이동시 벌레끼리 서로 통과 못하며, 서로 못 먹는다.
4.2. 합성(Synthesis)
- 자기 꼬리를 통과 못한다
애벌레 프로그램의 기본 베이스인 뱀 게임에서 아이디어를 얻었으며 애벌레의 머리가 꼬리에 부딪혔을 때 애벌레가 죽으면서 게임을 종료한다. 종료시 Game Over! 창이 뜨도록 한다.
4.3. 분석(Analysis) 및 구현(Build)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CCProject_20172804_20172829
{
public partial class Form1 : Form
{
const int BAB_NUM = 30;
int[,] game_pan = new int[33, 33];
int len, len_2;
int[] bugX = new int[90];
int[] bugY = new int[90];
int[] oldbugX = new int[90];
int[] oldbugY = new int[90];
int xDir, yDir, xDir_2, yDir_2;
int[] babx = new int[30];
int[] baby = new int[30];
int[] bugX_2 = new int[90];//두 번째 애벌레 머리랑 꼬리 저장
int[] bugY_2 = new int[90];
int[] oldbugX_2 = new int[90];
int[] oldbugY_2 = new int[90];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
GamePanInit();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
DrawGamePan(e.Graphics);
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
CursorControl(e.KeyCode);
}
private void timer1_Tick(object sender, EventArgs e)
{
Invalidate();
MovingBug();
}
void babGenerator()
{
int i, x, y;
Random rand = new Random();
for (i = 0; i < BAB_NUM; i++)
{
x = rand.Next() % 30 + 1;
y = rand.Next() % 30 + 1;
babx[i] = x;
baby[i] = y;
if (game_pan[y, x] == 0)
game_pan[y, x] = 2;
else
{
i = i - 1;
continue;
}
}
return;
}
void GamePanInit()
{
int i;
for (i = 0; i < 33; i++)
{
game_pan[i, 0] = -1;
game_pan[i, 32] = -1;
game_pan[0, i] = -1;
game_pan[32, i] = -1;
}
bugX[0] = 2; bugY[0] = 1;
bugX[1] = 1; bugY[1] = 1;
game_pan[bugY[0], bugX[0]] = 3;
game_pan[bugY[1], bugX[1]] = 3;
bugX_2[0] = 30; bugY_2[0] = 31;
bugX_2[1] = 31; bugY_2[1] = 31;
babGenerator();
len = 2;
len_2 = 2;
xDir = 1; yDir = 0;
xDir_2 = 1; yDir_2 = 0;
}
void DrawGamePan(Graphics g)
{
int x, y, i;
Pen blackPen = new Pen(Color.Black);
Pen redPen = new Pen(Color.Red);
Pen bluePen = new Pen(Color.Blue);
for (y = 0; y < 33; y++)
{
for (x = 0; x < 33; x++)
{
switch (game_pan[y, x])
{
case -1:
g.DrawRectangle(blackPen, x * 20, y * 20, 20, 20);
break;
case 2:
SolidBrush blackBrush = new SolidBrush(Color.Black);
g.FillEllipse(blackBrush, x * 20, y * 20, 20, 20);
break;
}
}
}
g.DrawEllipse(redPen, bugX[0] * 20, bugY[0] * 20, 20, 20);
g.DrawEllipse(redPen, bugX_2[0] * 20, bugY_2[0] * 20, 20, 20);
for (i = 1; i < len; i++)
g.DrawEllipse(bluePen, bugX[i] * 20, bugY[i] * 20, 20, 20);
for (i = 1; i < len_2; i++)
g.DrawEllipse(bluePen, bugX_2[i] * 20, bugY_2[i] * 20, 20, 20);
}
void CursorControl(Keys DirectKey)
{
//1p
switch (DirectKey)
{
case Keys.Left:
if (xDir == 1)
break;
if (game_pan[bugY[0], bugX[0] - 1] != -1)
{
xDir = -1;
yDir = 0;
}
break;
case Keys.Right:
if (xDir == -1)
break;
if (game_pan[bugY[0], bugX[0] + 1] != -1)
{
xDir = 1;
yDir = 0;
}
break;
case Keys.Up:
if (yDir == 1)
break;
if (game_pan[bugY[0] - 1, bugX[0]] != -1)
{
xDir = 0;
yDir = -1;
}
break;
case Keys.Down:
if (yDir == -1)
break;
if (game_pan[bugY[0] + 1, bugX[0]] != -1)
{
xDir = 0;
yDir = 1;
}
break;
}
//2p (머리방향이 다르기 때문에 1p와 부호 반대)
switch (DirectKey)
{
case Keys.A:
if (xDir_2 == -1)
break;
if (game_pan[bugY_2[0], bugX_2[0] - 1] != -1)
{
xDir_2 = 1;
yDir_2 = 0;
}
break;
case Keys.D:
if (xDir_2 == 1)
break;
if (game_pan[bugY_2[0], bugX_2[0] + 1] != -1)
{
xDir_2 = -1;
yDir_2 = 0;
}
break;
case Keys.W:
if (yDir_2 == -1)
break;
if (game_pan[bugY_2[0] - 1, bugX_2[0]] != -1)
{
xDir_2 = 0;
yDir_2 = 1;
}
break;
case Keys.S:
if (yDir_2 == 1)
break;
if (game_pan[bugY_2[0] + 1, bugX_2[0]] != -1)
{
xDir_2 = 0;
yDir_2 = -1;
}
break;
}
MovingBug();
Invalidate();
}
void MovingBug()
{
//1p 머리 따라 꼬리 움직이기
if (xDir != 0 || yDir != 0)
{
for (int i = 0; i < len; i++) // 머리랑 몸통 위치 저장
{
oldbugX[i] = bugX[i];
oldbugY[i] = bugY[i];
}
bugX[0] += xDir; //위치값 받아서 움직이기
bugY[0] += yDir;
for (int i = 0; i < len; i++) // 저장된 머리랑 몸통 위치 전달
{
bugX[i + 1] = oldbugX[i];
bugY[i + 1] = oldbugY[i];
}
}
//1p 먹이 먹으면 꼬리 늘어남
for (int i = 0; i < BAB_NUM; i++)
{
if (bugX[0] == babx[i] && bugY[0] == baby[i])
{
game_pan[bugY[0], bugX[0]] = 1; // 먹이 사라지게
len++; // 꼬리 늘어남
}
}
//2p 머리 따라 꼬리 움직이기
if (xDir_2 != 0 || yDir_2 != 0)
{
for (int j = 0; j < len_2; j++) // 머리랑 몸통 위치 저장
{
oldbugX_2[j] = bugX_2[j];
oldbugY_2[j] = bugY_2[j];
}
bugX_2[0] -= xDir_2;//위치값 받아서 움직이기, 2p는 머리 방향이 다르기 때문에 1p와 반대 부호
bugY_2[0] -= yDir_2;
for (int j = 0; j < len_2; j++)// 저장된 머리랑 몸통 위치 전달
{
bugX_2[j + 1] = oldbugX_2[j];
bugY_2[j + 1] = oldbugY_2[j];
}
}
//2p 먹이 먹으면 꼬리 늘어남
for (int i = 0; i < BAB_NUM; i++)
{
if (bugX_2[0] == babx[i] && bugY_2[0] == baby[i])
{
game_pan[bugY_2[0], bugX_2[0]] = 1;// 먹이 사라지게
len_2++;// 꼬리 늘어남
}
}
//1p 벽 막기
for (int y = 0; y < 33; y++)
{
for (int x = 0; x < 33; x++)
{
if (bugX[0] == 31 && game_pan[y, x] == -1)//오른쪽
{
xDir = 0;
}
if (bugX[0] == 1 && game_pan[y, x] == -1)//왼쪽
{
xDir = 0;
}
if (bugY[0] == 31 && game_pan[y, x] == -1)//아래쪽
{
yDir = 0;
}
if (bugY[0] == 1 && game_pan[y, x] == -1)//위쪽
{
yDir = 0;
}
}
}
//2p 벽 막기
for (int y = 0; y < 33; y++)
{
for (int x = 0; x < 33; x++)
{
if (bugX_2[0] == 31 && game_pan[y, x] == -1)//오른쪽
{
xDir_2 = 0;
}
if (bugX_2[0] == 1 && game_pan[y, x] == -1)//왼쪽
{
xDir_2 = 0;
}
if (bugY_2[0] == 1 && game_pan[y, x] == -1)//아래쪽
{
yDir_2 = 0;
}
if (bugY_2[0] == 31 && game_pan[y, x] == -1)//위쪽
{
yDir_2 = 0;
}
}
}
//1p 자신의 몸 통과 못하기, 몸끼리 부딪히면 게임 끝!
for (int i = 1; i < len; i++)
{
if (bugY[0] + yDir == bugY[i] && bugX[0] + xDir == bugX[i])
{
xDir = 0; //몸 부딪히면 못 움직이게
yDir = 0;
MessageBox.Show("Game Over!");
}
}
//2p 자신의 몸 통과 못하기, 몸끼리 부딪히면 게임 끝!
for (int i = 1; i < len_2; i++)
{
if (bugY_2[0] - yDir_2 == bugY_2[i] && bugX_2[0] - xDir_2 == bugX_2[i])
{
xDir_2 = 0; //몸 부딪히면 못 움직이게
yDir_2 = 0;
MessageBox.Show("Game Over!");
}
}
}
}
}
'학교' 카테고리의 다른 글
[2019-1] 자바프로그래밍 과제 (0) | 2021.08.12 |
---|---|
[2019-1] 디지털영상처리1 8장 과제 (0) | 2021.08.12 |
[2019-1] 디지털영상처리1 7장 과제 (0) | 2021.08.12 |
[2019-1] 디지털영상처리1 6장 과제 (0) | 2021.08.12 |
[2019-1] 멀티미디어통신 과제 (0) | 2021.08.12 |