1、C 语 言 制 作 五 子 棋五 子 棋 游 戏 是 一 个 深 受 人 们 喜 爱 的 游 戏 , 通 常 是 人 机 对 弈 , 本 程 序 设 计 为 人 与人 对 弈 , 一 方 执 黑 棋 , 一 方 执 白 棋 , 轮 流 走 棋 , 每 方 都 试 图 在 游 戏 结 束 前 让 自 己 的棋 子 五 子 相 连 。 按 键 盘 上 的 方 向 键 可 以 移 动 光 标 , 回 车 键 可 以 摆 放 棋 子 。一 、 设 计 目 的这 个 程 序 是 对 编 程 基 本 功 的 一 个 训 练 , 将 分 支 、 循 环 、 数 组 、 函 数 综 合 应 用 ,而 不 仅
2、限 于 编 制 独 立 的 小 程 序 , 通 过 游 戏 过 程 增 加 编 程 的 兴 趣 , 提 高 编 程 水 平 。 编制 该 程 序 我 对 以 下 的 知 识 点 进 行 的 巩 固 和 掌 握 : 1.数 组 元 素 为 结 构 体 的 数 组 应 用。 2.全 局 变 量 应 用 。 3.按 键 的 处 理 。 4.数 组 元 素 与 蛇 、 食 物 的 对 应 关 系 。 5.图形 方 式 等 等 。 虽 然 该 程 序 是 一 个 普 通 而 又 简 单 的 程 序 , 但 是 对 于 一 C 语 言 初 级阶 段 的 学 生 来 说 , 是 一 个 很 好 的 锻 炼
3、甚 至 可 以 说 是 一 个 很 好 的 提 高 。二 、 设 计 思 路棋 盘 设 计 为 1919 格 , 初 始 状 态 光 标 在 棋 盘 的 中 央 , 白 棋 先 走 , 轮 流 落 子 ,当 一 方 连 成 五 子 或 下 满 棋 盘 时 , 游 戏 结 束 ( 连 成 五 子 的 一 方 获 胜 , 下 满 棋 盘 为 和 棋) 。 当 游 戏 一 方 胜 利 后 显 示 胜 利 信 息 , 提 示 信 息 利 用 汉 字 点 阵 输 出 。从 程 序 表 面 看 , 这 是 一 个 二 维 平 面 图 , 所 以 数 据 用 二 维 数 组 来 表 示 , 数 组 两 个下
4、 标 可 以 表 示 棋 盘 上 的 位 置 , 数 组 元 素 的 值 代 表 棋 格 上 的 状 态 , 共 有 三 种 情 况 , 分别 是 0 代 表 空 格 , 1 代 表 白 棋 , 2 代 表 黑 棋 。 这 样 程 序 的 主 要 工 作 是 接 收 棋 手 按 键操 作 , 棋 手 1 用 Up、 Down、 Left、 Right 控 制 光 标 移 动 , 回 车 键 表 示 落 子 。 棋手 2 用 W、 S、 A、 D 控 制 光 标 移 动 , 空 格 键 表 示 落 子 。 一 旦 接 收 到 回 车 键 或 空 格键 , 说 明 棋 手 落 子 , 先 判 断
5、是 否 是 有 效 位 置 , 也 就 是 说 已 经 有 棋 子 的 位 置 不 能 重 叠落 子 。 落 子 成 功 后 , 马 上 判 断 以 该 位 置 为 中 心 的 八 个 方 向 : 上 、 下 、 左 、 右 、 左 上、 左 下 、 右 上 、 右 下 是 否 有 相 同 颜 色 的 棋 子 连 成 五 子 , 如 果 连 成 五 子 , 则 游 戏 结 束, 输 出 相 应 的 信 息 。 如 果 想 退 出 游 戏 , 可 以 按 Esc 键 。三 、 程 序 设 计1 定 义 全 局 变 量1. int gamespeed=5000; 2. int i,j,key; 3
6、. struct Sor 4. 5. int x; 6. int y;/*x,y 表 示 当 前 光 标 的 位 置 */ 7. int yesNN;/* 0 表 示 无 棋 子 , 1 表 示 白 色 棋 子 , 2 表 示 黑 色棋 子 */ 8. int kao;/* 1 表 示 白 棋 准 备 落 子 , 2 表 示 黑 棋 落 子 */ 9. int ok;/*1 表 示 白 棋 胜 出 , 2 表 示 黑 棋 胜 出 */ 10. sor; 2 Main()主 函 数按 照 语 法 规 则 , 首 先 定 义 使 用 到 的 常 数 、 全 局 变 量 、 函 数 原 型 说 明
7、。 棋 盘 状 态用 数 组 yes2020,初 值 为 0, 表 示 空 格 。 函 数 的 实 体 比 较 简 单 , 调 用 图 形 驱 动、 画 棋 盘 、 人 人 对 弈 等 自 定 义 函 数 , 一 旦 游 戏 结 束 后 , 关 闭 图 形 驱 动 , 程 序 结 束 。3 drawqp()画 棋 盘 函 数背 景 颜 色 设 为 黑 色 , 从 坐 标 (100, 100)开 始 每 隔 20 个 单 位 用 绿 色 画 一 条水 平 直 线 , 一 条 垂 直 线 , 构 成 棋 盘 , 用 循 环 语 句 实 现 。 画 线 函 数 line()的 参 数为 线 的 起
8、点 和 终 点 坐 标 , 注 意 要 计 算 正 确 。 函 数 setfillstyle()可 以 设 置 填 充 模式 和 填 充 颜 色 , fillellipse(int x,int xradius,int yradius)以 x 和 y 为 圆 心, xradius 和 yradius 为 水 平 和 垂 直 轴 画 一 填 充 椭 圆 , 当 xradius 和 yradius相 等 时 , 则 画 出 的 是 圆 , 用 它 表 示 棋 子 。4 win()判 断 是 否 胜 出 函 数本 函 数 根 据 每 次 落 子 的 位 置 , 分 别 向 上 、 下 、 左 、 右
9、、 左 上 、 左 下 、 右 上 、 右下 八 个 方 向 判 断 是 否 有 相 同 颜 色 的 棋 子 连 成 五 子 , 如 果 成 立 , 游 戏 就 结 束 , 并 显 示提 示 信 息 (如 :红 方 获 胜 ), 否 则 继 续 落 子 。5 Gameplay()双 人 对 战 函 数这 是 游 戏 进 行 的 函 数 , 主 要 是 接 收 棋 手 的 按 键 消 息 , 其 处 理 过 程 如 下 :(1) 按 Esc 键 程 序 可 以 随 时 结 束 。(2) 按 上 下 左 右 光 标 键 , 则 改 变 棋 子 移 动 的 坐 标 值 。(3) 按 回 车 键 后
10、判 断 :1) 如 落 子 的 位 置 已 经 有 棋 则 无 效 , 继 续 按 键 。2) 如 落 子 位 置 是 空 格 , 可 以 将 棋 子 落 入 格 内 , 调 用 win()函 数 。3) 如 果 棋 子 变 化 后 , 棋 盘 已 下 满 了 棋 子 , 则 游 戏 结 束 。 显 示 平 局 信 息 。(4) 重 复 上 述 步 骤 , 直 到 游 戏 结 束 。6 Xandy()显 示 光 标 纵 横 坐 标 函 数该 函 数 的 作 用 是 在 每 次 移 动 光 标 后 , 在 屏 幕 左 下 角 显 示 出 光 标 的 纵 横 坐 标 。7 图 形 功 能 函 数以
11、 下 函 数 原 形 都 在 graphics.h 中 。(1)registerbgidriver():(2)initgraph(int *driver, int *mode, char *path):用 于 初 始 化 图 形系 统 , 并 装 入 相 应 的 图 形 驱 动 器 。 该 函 数 把 由 driver 所 指 向 的 图 形 驱 动 器 代 码装 入 内 存 。 如 果 图 形 驱 动 器 未 装 入 内 存 , 图 形 函 数 将 不 能 操 作 。 图 形 函 数 所 用 的 屏显 模 式 由 mode 所 指 向 的 整 数 值 确 定 。 最 后 , 图 形 驱 动
12、器 的 路 径 是 由 path 所指 向 的 字 符 串 给 出 。 如 果 没 有 指 定 路 径 , 就 在 当 前 工 作 路 径 上 寻 找 。(3)rectangle(int left,int top,int right,int bottom):函 数 rectangle()用 当 前 画 出 由 坐 标 left,top 及 right,bottom 所 定 义 的 矩 形 。(4)setcolor(int color):把 当 前 画 线 颜 色 设 置 为 color 所 指 定 的 颜 色 。 每 个图 形 显 示 卡 的 有 效 颜 色 由 setpalette()提 供
13、 。(5)closegraph():该 函 数 使 图 形 状 态 失 效 , 并 且 释 放 用 于 保 存 图 形 驱 动 器 和字 体 的 系 统 内 存 。 当 你 的 程 序 既 用 到 图 形 输 出 又 用 到 非 图 形 输 出 时 , 应 该 用 此 函 数。 该 函 数 还 把 系 统 屏 显 模 式 返 回 到 调 用 initgragh()前 的 状 态 。通 过 编 制 该 程 序 我 对 以 下 的 知 识 点 进 行 的 巩 固 和 掌 握 : 1.数 组 元 素 为 结 构 体的 数 组 应 用 。 2.全 局 变 量 应 用 。 3.按 键 的 处 理 。 4
14、.图 形 方 式 等 等 。 虽 然 该 程 序 是一 个 普 通 而 又 简 单 的 程 序 , 但 是 对 于 一 C 语 言 初 级 阶 段 的 学 生 来 说 , 是 一 个 很 好的 锻 炼 甚 至 可 以 说 是 一 个 很 好 的 提 高 。 由 于 个 人 能 力 的 限 制 该 程 序 还 有 许 多 的 缺 陷, 若 要 进 一 步 的 完 善 还 需 要 对 C 语 言 更 深 一 步 的 学 习 。程 序 运 行 部 分 截 图 :1. #include 2. #define N 20 3. /*定 义 键 盘 */ 4. #define up 0x4800 5. #d
15、efine down 0x5000 6. #define left 0x4b00 7. #define right 0x4d00 8. #define esc 0x011b 9. #define enter 0x1c0d 10. #define A 0x1e61 11. #define S 0x1f73 12. #define D 0x2064 13. #define W 0x1177 14. #define space 0x3920 15. #define Y 0x1579 16. #define n 0x316e 17. int gamespeed=5000; 18. int i,j,ke
16、y; 19. struct Sor 20. 21. int x; 22. int y;/*x,y 表 示 当 前 光 标 的 位 置 */ 23. int yesNN;/* 0 表 示 无 棋 子 , 1 表 示 白 色 棋 子 , 2 表 示 黑 色棋 子 */ 24. int kao;/* 1 表 示 白 棋 准 备 落 子 , 2 表 示 黑 棋 落 子 */ 25. int ok;/*1 表 示 白 棋 胜 出 , 2 表 示 黑 棋 胜 出 */ 26. sor; 27. 28. void init(void) /*graph drive*/ 29. 30. int driver=D
17、ETECT,mode=0; 31. registerbgidriver(EGAVGA_driver); 32. initgraph( 33. 34. 35. void drawmat(char *mat,int matsize,int x,int y,int color) 36. 37. int i,j,k,m; 38. m=(matsize-1)/8+1; 39. for(j=0;jk) 43. putpixel(x+i*8+k,y+j,color); 44. 45. 46. void show(void)/*input word*/ 47. 48. drawmat(wu64H,64,438
18、,49,0); 49. drawmat(zi64H,64,488,49,0); 50. drawmat(qi64H,64,538,49,0); 51. 52. drawmat(wu64H,64,440,50,13); 53. drawmat(zi64H,64,490,50,13); 54. drawmat(qi64H,64,540,50,13); 55. 56. drawmat(zuo16H,16,480,450,8); 57. drawmat(zhe16H,16,498,450,8); 58. drawmat(tian16H,16,518,450,8); 59. drawmat(xue16H
19、,16,536,450,8); 60. drawmat(ke16H,16,554,450,8); 61. 62. 63. void drawqp(void)/*draw qi pan*/ 64. 65. setcolor(3); 66. for(i=50;i4 137. else 138. sor.ok=2; 139. break; 140. 141. 142. if(sor.ok!=0) 143. break; 144. 145. 146. 147.void gameover(void) 148. 149. if(sor.ok=1) 150. 151. drawmat(bai64H,64,4
20、88,119,0); 152. drawmat(bai64H,64,490,120,4); 153. 154. else 155. 156. drawmat(hong64H,64,488,119,0); 157. drawmat(hong64H,64,490,120,4); 158. 159. 160. drawmat(fang64H,64,488,189,0); 161. drawmat(huo64H,64,488,259,0); 162. drawmat(sheng64H,64,488,329,0); 163. 164. drawmat(fang64H,64,490,190,4); 165
21、. drawmat(huo64H,64,490,260,4); 166. drawmat(sheng64H,64,490,330,4); 167. 168. 169.void xandy(void)/*显 示 光 标 的 横 纵 坐 标 */ 170. 171. char str110,str210; 172. setfillstyle(SOLID_FILL,7); 173. bar(50,440,205,470); 174. setcolor(14); 175. settextstyle(0,0,2); 176. sprintf(str1,“X:%d“,(sor.x-30)/20); 177
22、. sprintf(str2,“Y:%d“,(sor.y-30)/20); 178. outtextxy(60,450,str1); 179. outtextxy(135,450,str2); 180. 181. 182.void gameplay(void) 183. 184. for(i=1;i50place(); 205. sor.y-=20; 206. 207. else if(key=downplace(); 215. sor.x-=20; 216. 217. else if(key=rightplace(); 227. sor.y-=20; 228. 229. else if(ke
23、y=Splace(); 237. sor.x-=20; 238. 239. else if(key=D 31. 32. / 定 义 各 对 象 的 形 状 ,注 意 是 宽 字 符 ,顺 序 同 上 . 33. char mySharps3 = “, “ “, “, “ “, “ “; 34. 35. / 定 义 蛇 的 运 动 方 向 上 |下 |左 |右 36. #define DIR_UP 1 37. #define DIR_DOWN 2 38. #define DIR_LEFT 3 39. #define DIR_RIGHT 4 40. 41. typedef struct _Snak
24、eBody 42. 43. uint8 x, y; 44. POINT2D, *PPOINT2D; 45. 46. POINT2D mySnakeMAP_WIDTH*MAP_HEIGHT = 0; 47. POINT2D myFood = 0; 48. int snakeLength = 0; 49. int snakeDir = DIR_RIGHT; 50. int isFood = 0; 51. int isOver = 0; 52. 53. void drawMap(void); 54. void initSnake(int len); 55. void drawSnake(void);
25、 56. void moveSnake(void); 57. void drawBlock(int x, int y, int bs); 58. int isInSnake(int x, int y); 59. void drawFood(void); 60. 61. int main() 62. 63. int isPause = 1; 64. fixConsoleSize(MAP_WIDTH + 2) * 2, MAP_HEIGHT + 2); 65. setCursorVisible(0); 66. setConsoleTitle(“Snake by RedOC. 2009.06.27“
26、); 67. initSnake(SNAKE_MIN_LEN); 68. drawMap(); 69. drawSnake(); 70. while (!isOver) 71. 72. if (!isPause) 73. 74. moveSnake(); 75. if (!isFood) 76. drawFood(); 77. 78. delayMS(200 - snakeLength*2); 79. if (jkHasKey() 80. 81. switch (jkGetKey() 82. 83. case JK_UP: 84. if (snakeDir != DIR_DOWN) 85. s
27、nakeDir = DIR_UP; 86. break; 87. case JK_DOWN: 88. if (snakeDir != DIR_UP) 89. snakeDir = DIR_DOWN; 90. break; 91. case JK_LEFT: 92. if (snakeDir != DIR_RIGHT) 93. snakeDir = DIR_LEFT; 94. break; 95. case JK_RIGHT: 96. if (snakeDir != DIR_LEFT) 97. snakeDir = DIR_RIGHT; 98. break; 99. case JK_ESC: 1
28、00. case JK_ENTER: 101. case JK_SPACE: 102. isPause = !isPause; 103. break; 104. default: 105. break; 106. 107. 108. 109. gotoTextPos(MAP_BASE_X + MAP_WIDTH / 2 + 2, MAP_BASE_Y + MAP_HEIGHT / 2); 110. printf(“Game Over! Score: %d.“, snakeLength - SNAKE_MIN_LEN); 111. getch(); 112. return 0; 113. 114
29、. 115.void drawMap(void) 116. 117. int i, j; 118. setTextColor(myColorsBS_SPACE); 119. for (i = 0; i = MAP_WIDTH | hy = MAP_HEIGHT | isInSnake(hx, hy) 190. 191. isOver = 1; 192. return; 193. 194. if (hx = myFood.x 197. isFood = 0; 198. 199. else 200. drawBlock(mySnakesnakeLength-1.x, mySnakesnakeLen
30、gth-1.y, BS_SPACE); 201. for (i = snakeLength - 1; i = 0; i-) 202. 203. mySnakei+1.x = mySnakei.x; 204. mySnakei+1.y = mySnakei.y; 205. 206. mySnake0.x = hx; 207. mySnake0.y = hy; 208. drawSnake(); 209. return; 210. 211. 212.void drawBlock(int x, int y, int bs) 213. 214. if (x = MAP_WIDTH) 215. retu
31、rn; 216. if (y = MAP_HEIGHT) 217. return; 218. gotoTextPos(MAP_BASE_X + x)*2, MAP_BASE_Y + y); 219. setTextColor(myColorsbs); 220. printf(“%2s“, mySharpsbs); 221. return; 222. 223. 224.int isInSnake(int x, int y) 225. 226. int i; 227. for (i = 0; i #include #include #include 函数名 功能 void main() 游戏主程序
32、void Init(void); 图形驱动void Close(void); 图形结束void DrawK(void); 开始画面void GameOver(void); 结束游戏void GamePlay(void); 玩游戏具体过程void PrScore(void); 输出成绩(3)总体设计思想: 利用图形驱动,制作美观的游戏界面.通过随机函数产生随机数,控制游戏过程食物的出现.定义键盘操作,控制游戏过程蛇的移动方向.画出边界,并判断游戏是否结束.统计游戏过程蛇吃的食物数量,计算并输出游戏成绩.(4)程序有待改进的地方及本次实习的收获和建议 收获:加深认识了程序编译过程的中 团队合作的重
33、要性.提高了自己的编程能力(5)源程序清单(主要代码)#define N 200 #include #include #include #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;/*判断是否要出现食物的变量 */
34、 food;/*食物的结构体 */ struct Snake int xN; int yN; 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);/*输出成绩*/ /*主函数 */
35、void main(void) Init();/*图形驱动*/ DrawK();/*开始画面*/ GamePlay();/*玩游戏具体过程 */ Close();/*图形结束*/ /*图形驱动 */ void Init(void) int gd=DETECT,gm; initgraph( cleardevice(); /*开始画面,左上角坐标为(50 ,40 ),右下角坐标为(610,460)的围墙*/ void DrawK(void) /*setbkcolor(LIGHTGREEN);*/ setcolor(11); setlinestyle(SOLID_LINE,0,THICK_WIDTH
36、);/*设置线型*/ for(i=50;i0;i-)/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/ snake.xi=snake.xi-1; snake.yi=snake.yi-1; /*1,2,3,4 表示右,左,上,下四个方向,通过这个判断来移动蛇头*/ switch(snake.direction) case 1:snake.x0+=10;break; case 2: snake.x0-=10;break; case 3: snake.y0-=10;break; case 4: snake.y0+=10;break; for(i=3;i595|snake.y0455)/*蛇是否撞到
37、墙壁 */ GameOver();/*本次游戏结束*/ snake.life=1; /*蛇死*/ if(snake.life=1)/*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/ break; if(snake.x0=food.x/*把画面上的食物东西去掉*/ rectangle(food.x,food.y,food.x+10,food.y-10); snake.xsnake.node=-20;snake.ysnake.node=-20; /*新的一节先放在看不见的位置,下次循环就取前一节的位置*/ snake.node+;/*蛇的身体长一节 */ food.yes=1;/*画面上需要
38、出现新的食物*/ score+=10; PrScore();/*输出新得分 */ setcolor(4);/*画出蛇*/ for(i=0;isnake.node;i+) rectangle(snake.xi,snake.yi,snake.xi+10, snake.yi-10); delay(gamespeed); setcolor(0);/*用黑色去除蛇的的最后一节*/ rectangle(snake.xsnake.node-1,snake.ysnake.node-1, snake.xsnake.node-1+10,snake.ysnake.node-1-10); /*endwhile(!kb
39、hit )*/ if(snake.life=1)/*如果蛇死就跳出循环*/ break; key=bioskey(0);/*接收按键*/ if(key=ESC)/*按 ESC 键退出*/ break; else if(key=UP else if(key=RIGHT else if(key=LEFT else if(key=DOWN /*endwhile(1)*/ /*游戏结束 */ void GameOver(void) cleardevice(); PrScore(); setcolor(RED); settextstyle(0,0,4); outtextxy(200,200,“GAME OVER“); getch(); /*输出成绩 */ void PrScore(void) char str10; 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();