Skip to content

Instantly share code, notes, and snippets.

@jabbany
Last active December 18, 2015 04:49
Show Gist options
  • Save jabbany/5728100 to your computer and use it in GitHub Desktop.
Save jabbany/5728100 to your computer and use it in GitHub Desktop.
THU大作业,贪食,C...
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<time.h>
#define roof(a, b) (a+b)%b
/*
记得改掉!!
Name: 贪食蛇
Copyright: 无
Author: 麦萌
Date: 07-06-13 16:34
Description: 一个很弱的贪食蛇游戏。。。太弱了以至于刷新都卡>___>
*/
/** 游戏场地, 20x30的 **/
int field[20][30];
/** 游戏状态
0 - 欢迎界面
1 - 游戏中
2 - 高分榜
**/
int gameState = 0;
/** 蛇面对的方向
0 - 上
1 - 下
2 - 左
3 - 右
**/
int snakeFace = 0, faceUpdated = 0;
int snakeX = 0, snakeY = 0;
int score = 0;
void printWelcome(){
/** 输出欢迎文字 **/
if(gameState != 0)
return;
printf("===贪食蛇===\n");
printf("(1) 进入游戏\n");
printf("(2) 高分排行榜\n");
printf("(3) 退出游戏\n");
printf("请按下相应的数字键来选择模式:");
}
void printField(){
/** 绘制场地 **/
system("cls");
for(int i = 0; i <= 20; i++){
for(int j = 0; j < 30; j++){
if( i == 20 ){
printf("一");
continue;
}
if(field[i][j] == 0){
printf(" ");
}else if(field[i][j] > 0){
printf("口");
}else{
printf("〇");
}
}
printf("|\n");
}
printf("按键:w - 上 | a - 左 | s - 下 | d - 右 | ESC - 退出到主屏\n");
printf("得分:%i", score);
}
void appendScore(){
FILE *fp;
fp = fopen("results.dat","a");
if(fp == NULL){
printf("没办法写入文件,请检查磁盘可写并且你有权限!\n");
return;
}
fprintf(fp, "%d\n",score);
fclose(fp);
}
void snakeDie(){
system("cls");
appendScore();
printf("================\n");
printf("啊啦,你死了。你得到了 %i 分\n 按任意键重新开始游戏...\n", score);
for(int i = 0; i < 20; i++)
for(int j = 0; j < 20; j++)
field[i][j] = 0;
score = 0;
snakeFace = 0;
snakeX = 0;
snakeY = 0;
gameState = 0;
printf("================\n");
getch();
}
void generatePellet(){
if(score < 450){
/** 蛇长小于场地75%的时候,随即选食物点 **/
srand(time(NULL));
int xycoords = rand() % 600;
int x = xycoords / 20;
int y = xycoords % 20;
while(field[y][x] != 0){
/** 有东西了,重新生成新的坐标 **/
xycoords = rand() % 600;
x = xycoords / 20;
y = xycoords % 20;
}
field[y][x] = -1;
}else{
/** 蛇长大于场地75%了,随机选择可能会产生很多冲撞
所以只从剩下的空里面选择
**/
int totalSpaces = 0;
for(int i = 0; i < 20; i++)
for(int j = 0; j < 30; j++){
if(field[i][j] == 0)
totalSpaces++;
}
if(totalSpaces == 0)
return; /** 卧槽!你TM玩赢了?! **/
/** 从空余的个数里面选一个 **/
int spaceSelected = rand() % totalSpaces;
for(int i = 0; i < 20; i++)
for(int j = 0; j < 30; j++){
totalSpaces--;
if(totalSpaces == spaceSelected)
field[i][j] = -1;
}
}
}
void moveSnakeBody(){
/** 搜索蛇的尾巴并删掉 **/
int tailX = snakeX, tailY = snakeY, lastX = -1, lastY = -1;
while(field[tailY][tailX] > 1){
int ptr = field[tailY][tailX];
lastX = tailX;
lastY = tailY;
tailX = (ptr - 2) / 20;
tailY = (ptr - 2) % 20;
}
field[tailY][tailX] = 0;
if(lastX >= 0 && lastY >= 0)
field[lastY][lastX] = 1;
}
void moveSnake(){
/** 移动蛇体 **/
bool grow = false;
switch(snakeFace){
case 0:
if(field[roof(snakeY - 1,20)][snakeX] < 0)
grow = true;
else if(field[roof(snakeY - 1,20)][snakeX] > 0){
snakeDie();
return;
}
field[roof(snakeY - 1,20)][snakeX] = snakeX * 20 + snakeY + 2;
snakeY = roof(snakeY - 1,20);
break;
case 1:
if(field[roof(snakeY + 1,20)][snakeX] < 0)
grow = true;
else if(field[roof(snakeY + 1,20)][snakeX] > 0){
snakeDie();
return;
}
field[roof(snakeY + 1,20)][snakeX] = snakeX * 20 + snakeY + 2;
snakeY = roof(snakeY + 1,20);
break;
case 2:
if(field[snakeY][roof(snakeX - 1,30)] < 0)
grow = true;
else if(field[snakeY][roof(snakeX - 1,30)] > 0){
snakeDie();
return;
}
field[snakeY][roof(snakeX - 1,30)] = snakeX * 20 + snakeY + 2;
snakeX = roof(snakeX - 1,30);
break;
case 3:
if(field[snakeY][roof(snakeX + 1,30)] < 0)
grow = true;
else if(field[snakeY][roof(snakeX + 1,30)] > 0){
snakeDie();
return;
}
field[snakeY][roof(snakeX + 1,30)] = snakeX * 20 + snakeY + 2;
snakeX = roof(snakeX + 1,30);
break;
}
faceUpdated = snakeFace;
if(!grow)
moveSnakeBody();
else{
generatePellet();
score++;
}
}
int main(void){
init: /** 老天大概会谴责我的 **/
while( gameState == 0 ){
printWelcome();
char c = getche();
switch(c){
case '1':
gameState = 1;
goto game;
break;
case '2':
gameState = 2;
goto highscore;
break;
case '3':
return 0;
default:
printf("\n您的输入'%c'有误,请重新输入!\n\n", c);
}
}
highscore:
while( gameState == 2 ){
printf("\n\n下面是最高分TOP 10\n================\n");
FILE *fp;
fp = fopen("results.dat", "r");
if(fp == NULL){
printf("呵呵,没记录。\n");
}else{
int scores[2048], i, cur = 0;
while(fscanf(fp, "%d\n", &i) == 1){
scores[cur] = i;
cur++;
}
//Sort the scores
for(int a = 1; a < cur; a++){
int val = scores[a];
int hole = a;
while(hole > 0 && val > scores[hole - 1]){
scores[hole] = scores[hole - 1];
hole--;
}
scores[hole] = val;
}
for(int a = 0; a < (cur > 10? 10: cur); a++){
printf("%d: 得分 %d\n", a+1, scores[a]);
}
fclose(fp);
}
printf("==============\n输入任意键返回菜单...\n");
char k = getch();
switch(k){
default:
gameState = 0;
goto init;
}
}
goto init;
game:
/** 初始化蛇 **/
field[9][14] = 1;
snakeX = 14;
snakeY = 9;
generatePellet();
clock_t tlast = clock(), tcurr;
while( gameState == 1 ){
tcurr = clock();
clock_t tdiff = tcurr - tlast;
if(tdiff > 500){
/** 500ms 绘制场地 **/
tlast = tcurr;
printField();
moveSnake();
}
if( kbhit() ){
/** 抓键盘 **/
char ch = getch();
switch(ch){
case 'w':
if(faceUpdated > 1)
snakeFace = 0;
break;
case 'a':
if(faceUpdated < 2)
snakeFace = 2;
break;
case 's':
if(faceUpdated > 1)
snakeFace = 1;
break;
case 'd':
if(faceUpdated < 2)
snakeFace = 3;
break;
case 27:
system("cls");
appendScore();
printf("========\n分数已经保存,按任意键返回主菜单...\n========\n");
gameState = 0;
getch();
goto init;/** 老天要谴责我了 **/
break;
}
}
}
goto init;
return 0;
}
@Xuanwo
Copy link

Xuanwo commented Jun 2, 2014

代码不错,就是屏幕的刷新好蛋疼= =,难道真要用OpenGL之类的东西来写?

@jabbany
Copy link
Author

jabbany commented Jun 2, 2014

嗯。。。命令行+Windows下目测没什么别的办法。。。
Linux下能用curses做出更好的刷新。
简单的贪食蛇SDL就可以写,做成3D的话也可以用SDL或者原生写 OpenGL(蛋疼)。。。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment