• 欢迎访问C语言网www.dotcpp.com 比赛栏每月有奖月赛!举办比赛联系QQ:2045302297
  • 问题反馈、粉丝交流 QQ群327452739 蓝桥杯训练群:113766799 申请群时请备注排名里的昵称
  • C语言研究中心 为您提供有图、有料、解渴的C语言专题! 欢迎讨论!

C语言版五子棋游戏(VC6.0实现)

C语言研究中心 CTO 30135次浏览 9个评论

C语言实现五子棋游戏,编译运行后如图

上下左右移动光标位置,空格为下子,黑白交替,可以自娱自乐~

运行效果如下:

C语言版五子棋游戏(VC6.0实现)

 

编译器Vc6.0,亲自无问题

代码如下:

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <conio.h>
  4. #include <string.h>
  5. #define MAXIMUS 15 //定义棋盘大小
  6. int p[MAXIMUS][MAXIMUS];//存储对局信息
  7. char buff[MAXIMUS*2+1][MAXIMUS*4+3];//输出缓冲器
  8. int Cx,Cy;//当前光标位置
  9. int Now;//当前走子的玩家,1代表黑,2代表白
  10. int wl,wp;//当前写入缓冲器的列数和行数位置
  11. char* showText;//在棋盘中央显示的文字信息
  12. int count;//回合数
  13. char* Copy(char* strDest,const char* strSrc)//修改过的字符串复制函数,会忽略末端的\0
  14. {
  15. char* strDestCopy = strDest;
  16. while (*strSrc!='\0')
  17. {
  18. *strDest++=*strSrc++;
  19. }
  20. return strDestCopy;
  21. }
  22. void Initialize()//初始化一个对局函数
  23. {
  24. int i,j;//循环变量
  25. showText="";//重置显示信息
  26. count=0;//回合数归零
  27. for(i=0;i<MAXIMUS;i++)//重置对局数据
  28. {
  29. for(j=0;j<MAXIMUS;j++)
  30. {
  31. p[i][j]=0;
  32. }
  33. }
  34. Cx=Cy=MAXIMUS/2;//重置光标到中央
  35. Now=1;//重置当前为黑方
  36. }
  37. char* getStyle(int i,int j)//获得棋盘中指定坐标交点位置的字符,通过制表符拼成棋盘
  38. {
  39. if(p[i][j]==1)//1为黑子
  40. return "●";
  41. else if(p[i][j]==2)//2为白子
  42. return "○";
  43. else if(i==0&&j==0)//以下为边缘棋盘样式
  44. return "┏";
  45. else if(i==MAXIMUS-1&&j==0)
  46. return "┓";
  47. else if(i==MAXIMUS-1&&j==MAXIMUS-1)
  48. return "┛";
  49. else if(i==0&&j==MAXIMUS-1)
  50. return "┗";
  51. else if(i==0)
  52. return "┠";
  53. else if(i==MAXIMUS-1)
  54. return "┨";
  55. else if(j==0)
  56. return "┯";
  57. else if(j==MAXIMUS-1)
  58. return "┷";
  59. return "┼";//中间的空位
  60. }
  61. char* getCurse(int i,int j)
  62. {//获得指定坐标交点位置左上格的样式,通过制表符来模拟光标的显示
  63. if(i==Cx)
  64. {
  65. if(j==Cy)
  66. return "┏";
  67. else if (j==Cy+1)
  68. return "┗";
  69. }
  70. else if(i==Cx+1)
  71. {
  72. if(j==Cy)
  73. return "┓";
  74. else if (j==Cy+1)
  75. return "┛";
  76. }
  77. return " ";//如果不在光标附近则为空
  78. }
  79. void write(char* c)//向缓冲器写入字符串
  80. {
  81. Copy(buff[wl]+wp,c);
  82. wp+=strlen(c);
  83. }
  84. void ln()//缓冲器写入位置提行
  85. {
  86. wl+=1;
  87. wp=0;
  88. }
  89. void Display()//将缓冲器内容输出到屏幕
  90. {
  91. int i,l=strlen(showText);//循环变量,中间文字信息的长度
  92. int Offset=MAXIMUS*2+2-l/2;//算出中间文字信息居中显示所在的横坐标位置
  93. if(Offset%2==1)//如果位置为奇数,则移动到偶数,避免混乱
  94. {
  95. Offset--;
  96. }
  97. Copy(buff[MAXIMUS]+Offset,showText);//讲中间文字信息复制到缓冲器
  98. if(l%2==1)//如果中间文字长度为半角奇数,则补上空格,避免混乱
  99. {
  100. *(buff[MAXIMUS]+Offset+l)=0x20;
  101. }
  102. system("cls");//清理屏幕,准备写入
  103. for(i=0;i<MAXIMUS*2+1;i++){//循环写入每一行
  104. printf("%s",buff[i]);
  105. if(i<MAXIMUS*2)//写入完每一行需要换行
  106. printf("\n");
  107. }
  108. }
  109. void Print()//将整个棋盘算出并储存到缓冲器,然后调用Display函数显示出来
  110. {
  111. int i,j;//循环变量
  112. wl=0;
  113. wp=0;
  114. for(j=0;j<=MAXIMUS;j++)//写入出交点左上角的字符,因为需要打印棋盘右下角,所以很以横纵各多一次循环
  115. {
  116. for(i=0;i<=MAXIMUS;i++)
  117. {
  118. write(getCurse(i,j));//写入左上角字符
  119. if(j==0||j==MAXIMUS)//如果是棋上下盘边缘则没有连接的竖线,用空格填充位置
  120. {
  121. if(i!=MAXIMUS)
  122. write(" ");
  123. }
  124. else//如果在棋盘中间则用竖线承接上下
  125. {
  126. if(i==0||i==MAXIMUS-1)//左右边缘的竖线更粗
  127. write("┃");
  128. else if(i!=MAXIMUS)//中间的竖线
  129. write("│");
  130. }
  131. }
  132. if(j==MAXIMUS)//如果是最后一次循环,则只需要处理边侧字符,交点要少一排
  133. {
  134. break;
  135. }
  136. ln();//提行开始打印交点内容
  137. write(" ");//用空位补齐位置
  138. for(i=0;i<MAXIMUS;i++)//按横坐标循环正常的次数
  139. {
  140. write(getStyle(i,j));//写入交点字符
  141. if(i!=MAXIMUS-1)//如果不在最右侧则补充一个横线承接左右
  142. {
  143. if(j==0||j==MAXIMUS-1)
  144. {
  145. write("━");//上下边缘的横线更粗
  146. }
  147. else
  148. {
  149. write("—");//中间的横线
  150. }
  151. }
  152. }
  153. ln();//写完一行后提行
  154. }
  155. Display();//将缓冲器内容输出到屏幕
  156. }
  157. int Put(){//在当前光标位置走子,如果非空,则返回0表示失败
  158. if(p[Cx][Cy]==0)
  159. {
  160. p[Cx][Cy]=Now;//改变该位置数据
  161. return 1;//返回1表示成功
  162. }
  163. else
  164. {
  165. return 0;
  166. }
  167. }
  168. int Check()//胜负检查,即判断当前走子位置有没有造成五连珠的情况
  169. {
  170. int w=1,x=1,y=1,z=1,i;//累计横竖正斜反邪四个方向的连续相同棋子数目
  171. for(i=1;i<5;i++)if(Cy+i<MAXIMUS&&p[Cx][Cy+i]==Now)w++;else break;//向下检查
  172. for(i=1;i<5;i++)if(Cy-i>0&&p[Cx][Cy-i]==Now)w++;else break;//向上检查
  173. if(w>=5)return Now;//若果达到5个则判断当前走子玩家为赢家
  174. for(i=1;i<5;i++)if(Cx+i<MAXIMUS&&p[Cx+i][Cy]==Now)x++;else break;//向右检查
  175. for(i=1;i<5;i++)if(Cx-i>0&&p[Cx-i][Cy]==Now)x++;else break;//向左检查
  176. if(x>=5)return Now;//若果达到5个则判断当前走子玩家为赢家
  177. for(i=1;i<5;i++)if(Cx+i<MAXIMUS&&Cy+i<MAXIMUS&&p[Cx+i][Cy+i]==Now)y++;else break;//向右下检查
  178. for(i=1;i<5;i++)if(Cx-i>0&&Cy-i>0&&p[Cx-i][Cy-i]==Now)y++;else break;//向左上检查
  179. if(y>=5)return Now;//若果达到5个则判断当前走子玩家为赢家
  180. for(i=1;i<5;i++)if(Cx+i<MAXIMUS&&Cy-i>0&&p[Cx+i][Cy-i]==Now)z++;else break;//向右上检查
  181. for(i=1;i<5;i++)if(Cx-i>0&&Cy+i<MAXIMUS&&p[Cx-i][Cy+i]==Now)z++;else break;//向左下检查 if(z>=5)return Now;//若果达到5个则判断当前走子玩家为赢家
  182. return 0;//若没有检查到五连珠,则返回0表示还没有玩家达成胜利
  183. }
  184. int RunGame()//进行整个对局,返回赢家信息(虽然有用上)
  185. {
  186. int input;//输入变量
  187. int victor;//赢家信息
  188. Initialize();//初始化对局
  189. while(1){//开始无限回合的死循环,直到出现胜利跳出
  190. Print();//打印棋盘
  191. input=getch();//等待键盘按下一个字符
  192. if(input==27)//如果是ESC则退出程序
  193. {
  194. exit(0);
  195. }
  196. else if(input==0x20)//如果是空格则开始走子
  197. {
  198. if(Put())//如果走子成功则判断胜负
  199. {
  200. victor=Check();
  201. Now=3-Now;//轮换当前走子玩家
  202. count++;
  203. if(victor==1)//如果黑方达到胜利,显示提示文字并等待一次按键,返回胜利信息
  204. {
  205. showText="黑方获得了胜利!";
  206. Print();
  207. if(getch()==0xE0)
  208. {
  209. getch();
  210. }
  211. return Now;
  212. }
  213. else if(victor==2)//如果白方达到胜利,显示提示文字并等待一次按键,返回胜利信息
  214. {
  215. showText="白方获得了胜利!";
  216. Display();
  217. if(getch()==0xE0)
  218. {
  219. getch();
  220. }
  221. return Now;
  222. }else if(count==MAXIMUS*MAXIMUS)//如果回合数达到了棋盘总量,即棋盘充满,即为平局
  223. {
  224. showText="平局!";
  225. Display();
  226. if(getch()==0xE0)
  227. {
  228. getch();
  229. }
  230. return 0;
  231. }
  232. }
  233. }
  234. else if(input==0xE0)//如果按下的是方向键,会填充两次输入,第一次为0xE0表示按下的是控制键
  235. {
  236. input=getch();//获得第二次输入信息
  237. switch(input)//判断方向键方向并移动光标位置
  238. {
  239. case 0x4B:Cx--; break;
  240. case 0x48:Cy--;break;
  241. case 0x4D:Cx++;break;
  242. case 0x50:Cy++;break;
  243. }
  244. if(Cx<0)Cx=MAXIMUS-1;//如果光标位置越界则移动到对侧
  245. if(Cy<0)Cy=MAXIMUS-1; if(Cx>MAXIMUS-1)Cx=0;
  246. if(Cy>MAXIMUS-1)Cy=0;
  247. }
  248. }
  249. }
  250. int main()//主函数
  251. {
  252. system("title 五-子-棋 -- c语言(dotcpp.com)研究中心");//设置标题
  253. system("mode con cols=63 lines=32");//设置窗口大小
  254. system("color E0");//设置颜色
  255. while(1)
  256. {//循环执行游戏
  257. RunGame();
  258. }
  259. }

C语言研究中心(www.dotcpp.com)

C语言网提供「C语言、C++、算法竞赛」在线课程,全部由资深研发工程师或ACM金牌大佬亲授课,更科学、全面的课程体系,以在线视频+在线评测的学习模式学习,学练同步,拒绝理论派,真正学会编程!还有奖学金等增值福利等你!

C语言网, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明C语言版五子棋游戏(VC6.0实现)
喜欢 (52)
[jinyangH@aliyun.com]
分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
(9)个小伙伴在吐槽
  1. 胜负检查的右上左下判断好像不起作用。
    鸽子2016-10-20 16:26 回复
    • 我想说这些代码放在哪都是红的怎么运行啊
      啦啦啦2019-04-25 13:52 回复
  2. 貌似点击什么键都没有反应哦?
    草木年华2016-10-21 10:56 回复
  3. 斜方向 有bug 个人水平还不够,你们自己改吧
    青村离奇2016-12-15 20:27 回复
    • 求指教
      学子2016-12-16 15:25 回复
    • 第181行后面少一行if(z>=5)return Now;
      pileilei2019-06-13 19:39 回复
  4. 用Code::Blocks编译,棋盘错位,棋格不能正常显示。
    C_Solver2018-02-02 16:05 回复
    • 用VS2017也是一样的错误!!!
      C_Solver2018-02-02 16:05 回复
  5. 你这个表格有问题啊
    局中人2020-07-14 06:37 回复