贪吃蛇源代码
求一个用c语言写的能在vc++正常编译的贪吃蛇源代码。想拿来看一下,学习一下。大神别藏起来了哈。Linux下代码#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include <signal.h>
#include <sys/time.h>
#define NUM 60
struct direct //用来表示方向的
{
int cx;
int cy;
};
typedef struct node //链表的结点
{
int cx;
int cy;
struct node *back;
struct node *next;
}node;
void initGame(); //初始化游戏
int setTicker(int); //设置计时器
void show(); //显示整个画面
void showInformation(); //显示游戏信息(前两行)
void showSnake(); //显示蛇的身体
void getOrder(); //从键盘中获取命令
void over(int i); //完成游戏结束后的提示信息
void creatLink(); //(带头尾结点)双向链表以及它的操作
void insertNode(int x, int y);
void deleteNode();
void deleteLink();
int ch; //输入的命令
int hour, minute, second; //时分秒
int length, tTime, level; //(蛇的)长度,计时器,(游戏)等级
struct direct dir, food; //蛇的前进方向,食物的位置
node *head, *tail; //链表的头尾结点
int main()
{
initscr();
initGame();
signal(SIGALRM, show);
getOrder();
endwin();
return 0;
}
void initGame()
{
cbreak(); //把终端的CBREAK模式打开
noecho(); //关闭回显
curs_set(0); //把光标置为不可见
keypad(stdscr, true); //使用用户终端的键盘上的小键盘
srand(time(0)); //设置随机数种子
//初始化各项数据
hour = minute = second = tTime = 0;
length = 1;
dir.cx = 1;
dir.cy = 0;
ch = 'A';
food.cx = rand() % COLS;
food.cy = rand() % (LINES-2) + 2;
creatLink();
setTicker(20);
}
//设置计时器(这个函数是书本上的例子,有改动)
int setTicker(int n_msecs)
{
struct itimerval new_timeset;
long n_sec, n_usecs;
n_sec = n_msecs / 1000 ;
n_usecs = ( n_msecs % 1000 ) * 1000L ;
new_timeset.it_interval.tv_sec= n_sec;
new_timeset.it_interval.tv_usec = n_usecs;
n_msecs = 1;
n_sec = n_msecs / 1000 ;
n_usecs = ( n_msecs % 1000 ) * 1000L ;
new_timeset.it_value.tv_sec = n_sec;
new_timeset.it_value.tv_usec = n_usecs ;
return setitimer(ITIMER_REAL, &new_timeset, NULL);
}
void showInformation()
{
tTime++;
if(tTime >= 1000000) //
tTime = 0;
if(1 != tTime % 50)
return;
move(0, 3);
//显示时间
printw("time: %d:%d:%d %c", hour, minute, second);
second++;
if(second > NUM)
{
second = 0;
minute++;
}
if(minute > NUM)
{
minute = 0;
hour++;
}
//显示长度,等级
move(1, 0);
int i;
for(i=0;i<COLS;i++)
addstr("-");
move(0, COLS/2-5);
printw("length: %d", length);
move(0, COLS-10);
level = length / 3 + 1;
printw("level: %d", level);
}
//蛇的表示是用一个带头尾结点的双向链表来表示的,
//蛇的每一次前进,都是在链表的头部增加一个节点,在尾部删除一个节点
//如果蛇吃了一个食物,那就不用删除节点了
void showSnake()
{
if(1 != tTime % (30-level))
return;
//判断蛇的长度有没有改变
bool lenChange = false;
//显示食物
move(food.cy, food.cx);
printw("@");
//如果蛇碰到墙,则游戏结束
if((COLS-1==head->next->cx && 1==dir.cx)
|| (0==head->next->cx && -1==dir.cx)
|| (LINES-1==head->next->cy && 1==dir.cy)
|| (2==head->next->cy && -1==dir.cy))
{
over(1);
return;
}
//如果蛇头砬到自己的身体,则游戏结束
if('*' == mvinch(head->next->cy+dir.cy, head->next->cx+dir.cx) )
{
over(2);
return;
}
insertNode(head->next->cx+dir.cx, head->next->cy+dir.cy);
//蛇吃了一个“食物”
if(head->next->cx==food.cx && head->next->cy==food.cy)
{
lenChange = true;
length++;
//恭喜你,通关了
if(length >= 50)
{
over(3);
return;
}
//重新设置食物的位置
food.cx = rand() % COLS;
food.cy = rand() % (LINES-2) + 2;
}
if(!lenChange)
{
move(tail->back->cy, tail->back->cx);
printw(" ");
deleteNode();
}
move(head->next->cy, head->next->cx);
printw("*");
}
void show()
{
signal(SIGALRM, show); //设置中断信号
showInformation();
showSnake();
refresh(); //刷新真实屏幕
}
void getOrder()
{
//建立一个死循环,来读取来自键盘的命令
while(1)
{
ch = getch();
if(KEY_LEFT == ch)
{
dir.cx = -1;
dir.cy = 0;
}
else if(KEY_UP == ch)
{
dir.cx = 0;
dir.cy = -1;
}
else if(KEY_RIGHT == ch)
{
dir.cx = 1;
dir.cy = 0;
}
else if(KEY_DOWN == ch)
{
dir.cx = 0;
dir.cy = 1;
}
setTicker(20);
}
}
void over(int i)
{
//显示结束原因
move(0, 0);
int j;
for(j=0;j<COLS;j++)
addstr(" ");
move(0, 2);
if(1 == i)
addstr("Crash the wall. Game over");
else if(2 == i)
addstr("Crash itself. Game over");
else if(3 == i)
addstr("Mission Complete");
setTicker(0); //关闭计时器
deleteLink(); //释放链表的空间
}
//创建一个双向链表
void creatLink()
{
node *temp = (node *)malloc( sizeof(node) );
head = (node *)malloc( sizeof(node) );
tail = (node *)malloc( sizeof(node) );
temp->cx = 5;
temp->cy = 10;
head->back = tail->next = NULL;
head->next = temp;
temp->next = tail;
tail->back = temp;
temp->back = head;
}
//在链表的头部(非头结点)插入一个结点
void insertNode(int x, int y)
{
node *temp = (node *)malloc( sizeof(node) );
temp->cx = x;
temp->cy = y;
temp->next = head->next;
head->next = temp;
temp->back = head;
temp->next->back = temp;
}
//删除链表的(非尾结点的)最后一个结点
void deleteNode()
{
node *temp = tail->back;
node *bTemp = temp->back;
bTemp->next = tail;
tail->back = bTemp;
temp->next = temp->back = NULL;
free(temp);
temp = NULL;
}
//删除整个链表
void deleteLink()
{
while(head->next != tail)
deleteNode();
head->next = tail->back = NULL;
free(head);
free(tail);
}windows下(最好用trubo c VC行也行麻烦点貌似要装easyx 应为有graphics.h)#define N 200
#include <graphics.h>
#include <stdlib.h>
#include <dos.h>
#define LEFT 0x4b00
#define RIGHT 0x4d00
#define DOWN 0x5000
#define UP 0x4800
#define ESC 0x011b
int i,key;
int score=0;/*得分*/
int gamespeed=50000;/*游戏速度自己调整*/
struct Food
{
int x;/*食物的横坐标*/
int y;/*食物的纵坐标*/
int yes;/*判断是否要出现食物的变量*/
}food;/*食物的结构体*/
struct Snake
{
int x;
int y;
int node;/*蛇的节数*/
int direction;/*蛇移动方向*/
int life;/* 蛇的生命,0活着,1死亡*/
}snake;
void Init(void);/*图形驱动*/
void Close(void);/*图形结束*/
void DrawK(void);/*开始画面*/
void GameOver(void);/*结束游戏*/
void GamePlay(void);/*玩游戏具体过程*/
void PrScore(void);/*输出成绩*/
/*主函数*/
void main(void)
{
Init();/*图形驱动*/
DrawK();/*开始画面*/
GamePlay();/*玩游戏具体过程*/
Close();/*图形结束*/
}
/*图形驱动*/
void Init(void)
{
int gd=DETECT,gm;
initgraph(&gd,&gm,"c:\\tc");
cleardevice();
}
/*开始画面,左上角坐标为(50,40),右下角坐标为(610,460)的围墙*/
void DrawK(void)
{
/*setbkcolor(LIGHTGREEN);*/
setcolor(11);
setlinestyle(SOLID_LINE,0,THICK_WIDTH);/*设置线型*/
for(i=50;i<=600;i+=10)/*画围墙*/
{
rectangle(i,40,i+10,49); /*上边*/
rectangle(i,451,i+10,460);/*下边*/
}
for(i=40;i<=450;i+=10)
{
rectangle(50,i,59,i+10); /*左边*/
rectangle(601,i,610,i+10);/*右边*/
}
}
/*玩游戏具体过程*/
void GamePlay(void)
{
randomize();/*随机数发生器*/
food.yes=1;/*1表示需要出现新食物,0表示已经存在食物*/
snake.life=0;/*活着*/
snake.direction=1;/*方向往右*/
snake.x=100;snake.y=100;/*蛇头*/
snake.x=110;snake.y=100;
snake.node=2;/*节数*/
PrScore();/*输出得分*/
while(1)/*可以重复玩游戏,压ESC键结束*/
{
while(!kbhit())/*在没有按键的情况下,蛇自己移动身体*/
{
if(food.yes==1)/*需要出现新食物*/
{
food.x=rand()()%400+60;
food.y=rand()()%350+60;
while(food.x%10!=0)/*食物随机出现后必须让食物能够在整格内,这样才可以让蛇吃到*/
food.x++;
while(food.y%10!=0)
food.y++;
food.yes=0;/*画面上有食物了*/
}
if(food.yes==0)/*画面上有食物了就要显示*/
{
setcolor(GREEN);
rectangle(food.x,food.y,food.x+10,food.y-10);
}
for(i=snake.node-1;i>0;i--)/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/
{
snake.x=snake.x;
snake.y=snake.y;
}
/*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/
switch(snake.direction)
{
case 1:snake.x+=10;break;
case 2: snake.x-=10;break;
case 3: snake.y-=10;break;
case 4: snake.y+=10;break;
}
for(i=3;i<snake.node;i++)/*从蛇的第四节开始判断是否撞到自己了,因为蛇头为两节,第三节不可能拐过来*/
{
if(snake.x==snake.x&&snake.y==snake.y)
{
GameOver();/*显示失败*/
snake.life=1;
break;
}
}
if(snake.x<55||snake.x>595||snake.y<55||
snake.y>455)/*蛇是否撞到墙壁*/
{
GameOver();/*本次游戏结束*/
snake.life=1; /*蛇死*/
}
if(snake.life==1)/*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/
break;
if(snake.x==food.x&&snake.y==food.y)/*吃到食物以后*/
{
setcolor(0);/*把画面上的食物东西去掉*/
rectangle(food.x,food.y,food.x+10,food.y-10);
snake.x=-20;snake.y=-20;
/*新的一节先放在看不见的位置,下次循环就取前一节的位置*/
snake.node++;/*蛇的身体长一节*/
food.yes=1;/*画面上需要出现新的食物*/
score+=10;
PrScore();/*输出新得分*/
}
setcolor(4);/*画出蛇*/
for(i=0;i<snake.node;i++)
rectangle(snake.x,snake.y,snake.x+10,
snake.y-10);
delay(gamespeed);
setcolor(0);/*用黑色去除蛇的的最后一节*/
rectangle(snake.x,snake.y,
snake.x+10,snake.y-10);
}/*endwhile(!kbhit)*/
if(snake.life==1)/*如果蛇死就跳出循环*/
break;
key=bioskey(0);/*接收按键*/
if(key==ESC)/*按ESC键退出*/
break;
else
if(key==UP&&snake.direction!=4)
/*判断是否往相反的方向移动*/
snake.direction=3;
else
if(key==RIGHT&&snake.direction!=2)
snake.direction=1;
else
if(key==LEFT&&snake.direction!=1)
snake.direction=2;
else
if(key==DOWN&&snake.direction!=3)
snake.direction=4;
}/*endwhile(1)*/
}
/*游戏结束*/
void GameOver(void)
{
cleardevice();
PrScore();
setcolor(RED);
settextstyle(0,0,4);
outtextxy(200,200,"GAME OVER");
getch()();
}
/*输出成绩*/
void PrScore(void)
{
char str;
setfillstyle(SOLID_FILL,YELLOW);
bar(50,15,220,35);
setcolor(6);
settextstyle(0,0,2);
sprintf(str,"score:%d",score);
outtextxy(55,20,str);
}
/*图形结束*/
void Close(void)
{
getch()();
closegraph();
} 还有 我是windows 而且没装trubo c 这到底能不能正常运行 我心里却是没底啊 本帖最后由 andalousie 于 2014-2-6 18:48 编辑
/***********************************************
* File: snake.cpp
* Author: Keith Schwarz (htiek@cs.stanford.edu)
*
* An implementation of the game "Snake" with a
* rudimentary computer AI player.The computer
* controls a snake that tries to eat as much food
* as possible.Every time it eats a food pellet,
* its length increases by one.The snake loses if
* it hits a wall or crashes into itself.
*
* The AI in this program is extremely simple.The
* snake moves forward, turning with probability 1/5
* at each step.If the snake's next step will
* certainly hit a wall, it tries to turn.
*
* In order to run this program, you will need to use
* a level file.A set of sample files are included
* in this directory.
*/
#include <iostream>
#include <string>
#include <deque>
#include <vector>
#include <fstream>
#include <cstdlib>
#include <ctime>
using namespace std;
/* Probability of turning at each step. */
const double kTurnRate = 0.2;
/* Time to wait, in seconds, between frames. */
const double kWaitTime = 0.1;
/* Number of food pellets that must be eaten to win. */
const size_t kMaxFood = 20;
/* Constants for the different tile types.Each level file is
* encoded using these characters.
*/
const char kEmptyTile = ' '; // Empty space
const char kWallTile= '#'; // Wall
const char kFoodTile= '
; // Food
const char kSnakeTile = '*'; // Snake start location/current position
/* The string used to clear the display before printing the game board.
* Windows systems should use CLS, Mac OS X or Linux users should use
* clear.
*/
const string kClearCommand = "CLS";
/* A struct encoding a point in a two-dimensional grid. */
struct pointT {
size_t row, col;
/* Utility constructor. */
pointT(size_t row, size_t col) {
this->row = row;
this->col = col;
}
/* Default constructor sets everything to 0. */
pointT() {
row = col = 0;
}
};
/* A struct containing relevant game information. */
struct gameT {
vector<string> world; // The playing field.Each string is
// composed of the characters encoding
// tiles and represents one row of the
// playing field.
size_t numRows, numCols; // Size of the playing field
deque<pointT> snake;// The snake body.The head is in the front
// of the deque and the tail in the back, so
// we can easily advance the snake a step
// forward
int dx, dy; // The snake direction
size_t numEaten; // How much food we've eaten.
};
/* Reads a line of text from the user. */
string GetLine() {
string result;
getline(cin, result);
return result;
}
/* Returns true with probability probability.This works by scaling
* down rand() by RAND_MAX so that we have a value in [0, 1) and returning
* whether the value is less than the set probability.
*/
bool RandomChance(double probability) {
return static_cast<double>(rand()) / RAND_MAX < probability;
}
/* Places a piece of food randomly on the board.This assumes that there
* is some free space remaining.
*/
void PlaceFood(gameT& game) {
while(true) {
size_t row = rand() % game.numRows;
size_t col = rand() % game.numCols;
/* If there isn't anything at the specified position, place the food there. */
if(game.world == kEmptyTile) {
game.world = kFoodTile;
return;
}
}
}
/* Clears the display and prints the game board. */
void PrintWorld(gameT& game) {
/* Use a system call to clear the display. */
system(kClearCommand.c_str());
/* Print each row. */
for(size_t i = 0; i < game.world.size(); ++i)
cout << game.world << endl;
cout << "Food eaten: " << game.numEaten << endl;
}
/* Given an ifstream to a file containing CORRECTLY-FORMATTED world data,
* loads in the world.
*
* The format used is as follows:
* Line 1: numRows numCols
* Line 2: dx dy
* Rest: World data
*
* We assume that the world is correctly-sized and that there is a single
* '*' character in the world that's the starting point for the snake.
*/
void LoadWorld(gameT& game, ifstream& input) {
/* Read in the number of rows and columns. */
input >> game.numRows >> game.numCols;
game.world.resize(game.numRows);
/* Read in the starting location. */
input >> game.dx >> game.dy;
/* Because we're going to be using getline() to read in the world
* data, we need to make sure that we consume the newline character
* at the end of the line containing the input data.We'll use
* getline() to handle this.This scans characters until it finds
* a newline, then consumes it.
*/
string dummy;
getline(input, dummy);
/* Read in the rows. */
for(size_t row = 0; row < game.numRows; ++row) {
getline(input, game.world);
/* Check to see if the * character (snake start position)
* is in this line.If so, make the snake.
*/
size_t col = game.world.find('*');
if(col != string::npos)
game.snake.push_back(pointT(row, col));
}
/* Set numEaten to zero - this needs to get done somewhere! */
game.numEaten = 0;
}
/* Helper function which returns whether a point is contained in the game
* grid.
*/
bool InWorld(pointT& pt, gameT& game) {
return pt.col < game.numCols &&
pt.row < game.numRows;
}
/* Returns whether, if the snake head is at position head, the snake
* has crashed.
*/
bool Crashed(pointT head, gameT& game) {
/* We crashed if the head is out of bounds, on a wall, or on another
* snake piece.
*/
return !InWorld(head, game) ||
game.world == kSnakeTile ||
game.world == kWallTile;
}
/* Returns the next position occupied by the head if the snake is moving
* in the direction dx, dy.
*/
pointT GetNextPosition(gameT& game, int dx, int dy) {
/* Get the head. */
pointT nextSpot = game.snake.front();
/* Update it. */
nextSpot.col += dx;
nextSpot.row += dy;
return nextSpot;
}
/* Performs AI logic to control the snake.The behavior is as follows:
* 1. If we aren't going to crash and we don't roll a 1 on a fair die,
* keep going straight.
* 2. Otherwise, check to see if we can turn left or right.Then randomly
* pick one safe choice.
*/
void PerformAI(gameT& game) {
/* Look where we're going to be next step. */
pointT nextSpot = GetNextPosition(game, game.dx, game.dy);
/* If this crashes us or we just feel like turning, turn. */
if(Crashed(nextSpot, game) || RandomChance(kTurnRate)) {
/* Compute what direction we'd be facing if we turned left or
* right.From linear algebra we have the following:
*
* For a left turn:
* |x'| |0 -1||x| --> x' = -y
* |y'| = |10||y| --> y' =x
*
* For a right turn:
* |x'| |01||x| --> x' =y
* |y'| = |-1 0||y| --> y' = -x
*/
int leftDx = -game.dy;
int leftDy =game.dx;
int rightDx =game.dy;
int rightDy = -game.dx;
/* Check if turning left or right will cause us to crash. */
bool canLeft = !Crashed(GetNextPosition(game, leftDx, leftDy), game);
bool canRight = !Crashed(GetNextPosition(game, rightDx, rightDy), game);
/* Now determine which direction to turn based on what direction
* we're facing.If we can choose either direction, pick one
* randomly.If we can't turn, don't.
*/
bool willTurnLeft;
if(!canLeft && !canRight)
return;
else if(canLeft && !canRight)
willTurnLeft = true;
else if(!canLeft && canRight)
willTurnLeft = false;
else
willTurnLeft = RandomChance(0.5);
/* Otherwise, based on the direction, turn appropriately. */
game.dx = willTurnLeft? leftDx : rightDx;
game.dy = willTurnLeft? leftDy : rightDy;
}
}
/* Moves the snake one step in its current direction and handles collisions
* and eating food.Returns true if we didn't crash, false if we did.
*/
bool MoveSnake(gameT& game) {
/* Compute new head. */
pointT nextHead = GetNextPosition(game, game.dx, game.dy);
/* Check for dead. */
if(Crashed(nextHead, game))
return false;
/* Remember whether we just ate food. */
bool isFood = (game.world == kFoodTile);
/* Update the display. */
game.world = kSnakeTile;
/* Push new head to the front of the deque. */
game.snake.push_front(nextHead);
/* If we got food, pick a new spot and don't remove the tail.This
* causes us to extend by one spot. */
if(isFood) {
PlaceFood(game);
++game.numEaten;
}
else {
/* Clear the tail and remove it from the snake. */
game.world = kEmptyTile;
game.snake.pop_back();
}
return true;
}
/* Pauses for a few milliseconds so we can see what's happening.This is
* implemented using a busy loop, which is less-than-optimal but doesn't
* require platform-specific features.
*/
void Pause() {
clock_t start = clock();
while(static_cast<double>(clock() - start) / CLOCKS_PER_SEC < kWaitTime);
}
/* Prompts the user for a filename, then loads the specified file. */
void InitializeGame(gameT& game) {
/* Seed the randomizer. */
srand(static_cast<int>(time(NULL)));
ifstream input;
while(true) {
cout << "Enter level file: ";
input.open(GetLine().c_str());
if(!input.fail()) break;
cout << "Sorry, I can't open that file." << endl;
input.clear();
}
LoadWorld(game, input);
}
/* Displays the result of the game. */
void DisplayResult(gameT& game) {
PrintWorld(game);
if(game.numEaten == kMaxFood)
cout << "Yay!The snake won!" << endl;
else
cout << "Oh no!The snake crashed!" << endl;
}
/* Runs the simulation and displays the result. */
void RunSimulation(gameT& game) {
/* Keep looping while we haven't eaten too much. */
while(game.numEaten < kMaxFood) {
PrintWorld(game);
PerformAI(game);
/* Move the snake and abort if we crashed. */
if(!MoveSnake(game))
break;
Pause();
}
DisplayResult(game);
}
/* The main program.Initializes the world, then runs the simulation. */
int main() {
gameT game;
InitializeGame(game);
RunSimulation(game);
return 0;
}
地图格式是15 15
1 0
###############
# #
# # # # # # # #
#$$ $#
# # # # # # # #
#$ #
# # # # # # # #
# * #
# # # # # # # #
# $#
# # # # # # # #
#$ $ $#
# # # # # # # #
# #
############### 看看而已,初学者 路过看看 = = 不明觉厉啊~~~
页:
[1]