3940931148926396110  

Game.h :
 

#ifndef GAME_H
#define GAME_H

#include<deque>

class game
{
public:
game();
game(int w,int h); //w: width, h:height
game(const game& g);
game& operator=(const game& g);
virtual ~game();

enum direction
{
UP,
DOWN,
LEFT,
RIGHT
};
enum obj
{
HEAD, //head of the snake
BODY, //body of the snake
WALL, //wall
FOOD, //food
EMPTY //nothing
};
class point
{
public:
int x,y;
point():x(-1),y(-1){}
point(int _x,int _y):x(_x),y(_y){}
};

protected:
obj** board;
direction towardsing;
int length;
bool _alive;
int _score;
std::deque<point> snake;

public:
int width; //width of the game board
int height;
float speed;

public: //interface
bool alive() const;
void on_timer();
void right();
int score() const;
void up();
void left();
void down();
bool set_speed(int s);
const obj *const * const state() const;

private:
};

#endif // GAME_H


game.cpp:

#include "game.h"
#include <assert.h>
#include <stdlib.h>

game::game()
{
game(1,1);
}

game::game(int w,int h)
{
int x;
int y;
this->width=w;
this->height=h;
this->board=new obj*[w];
for(int i=0;i<w;++i)
this->board[i]=new obj[h];
for(int i=0;i<w;++i)
for(int j=0;j<h;++j)
this->board[i][j]=EMPTY;
this->_alive=true;
this->speed=1;
this->_score=0;
this->towardsing=RIGHT;
this->length=1;
(this->snake).push_front(point(1,h/2));
(this->snake).push_front(point(2,h/2));
(this->snake).push_front(point(3,h/2));
for(int i=0;i<w;++i)
{
(this->board)[i][h-1]=WALL;
(this->board)[i][0]=WALL;
}
for(int i=0;i<h;++i)
{
(this->board)[w-1][i]=WALL;
(this->board)[0][i]=WALL;
}
while((this->board)[x=rand()%w][y=rand()%h]!=EMPTY);
(this->board)[x][y]=FOOD;
this->on_timer();
}

game::game(const game& g)
:snake(g.snake)
{
this->width=g.width;
this->height=g.height;
this->board=new obj*[this->width];
for(int i=0;i<this->width;++i)
this->board[i]=new obj[this->height];
for(int i=0;i<this->width;++i)
for(int j=0;j<this->height;++j)
this->board[i][j]=g.board[i][j];
this->_alive=g._alive;
this->_score=g._score;
this->speed=g.speed;
this->towardsing=g.towardsing;
this->length=g.length;
}

game& game::operator=(const game& g)
{
int i,j;
for(i=0;i<this->width;++i)
delete[] this->board[i];
delete[] this->board;
this->width=g.width;
this->height=g.height;
this->board=new obj*[g.width];
for(i=0;i<this->width;++i)
for(j=0;j<this->height;++j)
this->board[i][j]=g.board[i][j];
this->_alive=g._alive;
this->_score=g._score;
this->speed=g.speed;
this->towardsing=g.towardsing;
this->length=g.length;
this->snake=g.snake;
return *this;
}

game::~game()
{
for(int i=0;i<this->width;++i)
delete[] this->board[i];
delete[] this->board;
}

bool game::alive() const
{
return this->_alive;
}

int game::score() const
{
return this->_score;
}

bool game::set_speed(int s)
{
if (s<=0) return false;
this->speed=s;
return true;
}

void game::on_timer()
{
if(!this->_alive)return;
int x,y;
switch(this->towardsing)
{
case LEFT:
x=(this->snake[0]).x-1;
y=(this->snake[0]).y;
break;
case RIGHT:
x=(this->snake[0]).x+1;
y=(this->snake[0]).y;
break;
case UP:
x=(this->snake[0]).x;
y=(this->snake[0]).y-1;
break;
case DOWN:
x=(this->snake[0]).x;
y=(this->snake[0]).y+1;
break;
default:
assert(!"Unsupposed direction");
}
if(x<0)
x=this->width-1;
if(x>=this->width)
x=0;
if(y<0)
y=this->height-1;
if(y>=this->height)
y=0;
switch(this->board[x][y])
{
case EMPTY:
(this->board)[(this->snake).front().x][(this->snake).front().y]=BODY;
(this->snake).push_front(point(x,y));
(this->board)[x][y]=HEAD;
(this->board)[(this->snake).back().x][(this->snake).back().y]=EMPTY;
(this->snake).pop_back();
break;
case FOOD:
(this->board)[(this->snake).front().x][(this->snake).front().y]=BODY;
(this->snake).push_front(point(x,y));
(this->board)[x][y]=HEAD;
(this->_score)++;
while((this->board)[x=rand()%this->width][y=rand()%this->height]!=EMPTY);
(this->board)[x][y]=FOOD;
(this->speed)+=0.05;
break;
case WALL:
case BODY:
case HEAD:
(this->_alive)=false;
break;
default:
assert(!"Something strange");
}
}

void game::right()
{
if(this->towardsing==LEFT) return;
this->towardsing=RIGHT;
this->on_timer();
}

void game::left()
{
if(this->towardsing==RIGHT) return;
this->towardsing=LEFT;
this->on_timer();
}

void game::up()
{
if(this->towardsing==DOWN) return;
this->towardsing=UP;
this->on_timer();
}

void game::down()
{
if(this->towardsing==UP) return;
this->towardsing=DOWN;
this->on_timer();
}

const game::obj* const * const game::state() const
{
return this->board;
}



Main.cpp:


#include <windows.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "assert.h"
#include "game.h"

const int t=200;
int topscore=0;
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/* Make the class name into a global variable */
char szClassName[ ] = "CodeBlocksWindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
srand(time(0));
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */

/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);

/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default colour as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_WINDOW;

/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;

/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Snake raised by IF", /* Title Text */
WS_OVERLAPPED|WS_MINIMIZEBOX|WS_SYSMENU, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
430, /* The programs width */
490, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);

SetTimer(hwnd,1,t,0);
/* Make the window visible on the screen */
ShowWindow (hwnd, nCmdShow);

/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}

/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}


void paint(const game& g,HDC hdc)
{
char sc[128];
static HBRUSH hbbody=CreateSolidBrush(RGB(80,80,80));
static HBRUSH hbhead=CreateSolidBrush(RGB(20,20,20));
static HBRUSH hbempty=CreateSolidBrush(RGB(240,240,255));
static HBRUSH hbwall=CreateSolidBrush(RGB(255,55,55));
static HBRUSH hbfood=CreateSolidBrush(RGB(55,255,55));
static const int xoffset=10;
static const int yoffset=10;
static const int xlen=20;
static const int ylen=20;
HBRUSH hb;
for(int i=0;i<g.width;++i)
for(int j=0;j<g.height;++j)
{
switch(g.state()[i][j])
{
case game::HEAD:
hb=hbhead;
break;
case game::BODY:
hb=hbbody;
break;
case game::FOOD:
hb=hbfood;
break;
case game::WALL:
hb=hbwall;
break;
case game::EMPTY:
hb=hbempty;
break;
default:
assert(!"Something strange!");
}
SelectObject(hdc,hb);
Rectangle(hdc,xoffset+i*xlen,yoffset+j*ylen, xoffset+(i+1)*xlen, yoffset+(j+1)*ylen );
}
memset(sc,' ',127);
sc[127]=0;
TextOut(hdc,xoffset,yoffset+g.height*ylen,sc,strlen(sc));
if(g.alive())
sprintf(sc,"Your Score: %d",g.score());
else
sprintf(sc,"You are Dead! Your score is: %d ;Press Any Key to Restart",g.score());
TextOut(hdc,xoffset,yoffset+g.height*ylen,sc,strlen(sc));
sprintf(sc,"Top score: %d",topscore);
TextOut(hdc,xoffset,yoffset+g.height*ylen+ylen,sc,strlen(sc));
}

/* This function is called by the Windows function DispatchMessage() */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static game g=game(20,20);
static bool paused=false;
static float s=g.speed;
HDC hdc;
PAINTSTRUCT ps;
switch (message) /* handle the messages */
{
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
paint(g,hdc);
EndPaint(hwnd,&ps);
break;
case WM_TIMER:
hdc=GetDC(hwnd);
g.on_timer();
if(g.speed!=s)
{
s=g.speed;
SetTimer(hwnd,1,static_cast<unsigned int>(t/s),0);
}
if(!g.alive())
{
KillTimer(hwnd,1);
if(g.score()>topscore)
topscore=g.score();
}
paint(g,hdc);
ReleaseDC(hwnd,hdc);
break;
case WM_KEYDOWN:
switch(wParam)
{
case VK_UP:
g.up();
break;
case VK_DOWN:
g.down();
break;
case VK_LEFT:
g.left();
break;
case VK_RIGHT:
g.right();
break;
case VK_ESCAPE:
ExitProcess(0);
default:
if(!g.alive()) //restart
{
g.~game();
new(&g) game(20,20);
SetTimer(hwnd,1,t,0);
}
else // pause / continue
{
if (paused) SetTimer(hwnd,1,static_cast<unsigned int>(t/s),0);
else KillTimer(hwnd,1);
paused=!paused;
}
break;
}
hdc=GetDC(hwnd);
paint(g,hdc);
ReleaseDC(hwnd,hdc);
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}

return 0;
}
創作者介紹

資訊園

shadow 發表在 痞客邦 PIXNET 留言(0) 人氣()