C语言之三字棋

简介: 这个三字棋看似生活不起眼的小游戏,但是对于像我一样才开始接触C的人来说,实现起来也不是那样轻而易举。实现三字棋的过程,让我明白掌握代码并非最重要的,最重要的是,理清实现功能的逻辑,例如:实现这个游戏时,首先得了解游戏规则,其次需要一个棋盘......只要自己逻辑清晰,写代码也是水到渠成,还有一点,只要自己掌握逻辑,下次想再次实现这个功能或着分析已写的代码就不会犯怵了。最后我们要多善于整理总结,下次我们遇到类似的问题,就可以触类旁通了。

一.游戏介绍

三字棋又名井字棋,英文名叫Tic-Tac-Toe,是一种在3*3格子上进行的连珠游戏,和五子棋类似,由于棋盘一般不画边框,格线排成井字故得名。游戏需要的工具仅为纸和笔,然后由分别代表O和X的两个游戏者轮流在格子里留下标记(一般来说先手者为X),在程序中我们就不需要纸和笔,我们直接输入棋子坐标即可,然后由分别代表‘*’和‘#’的玩家和电脑轮流在格子里留下标记任意三个标记形成一条直线,则为获胜。

二.游戏实现思路

1.需要一个棋盘,用二维数组创建

char board[ROW][COL];//创建棋盘

2. 初始化棋盘,设计一个函数初始化棋盘

Initboard(board,ROW,COL);//初始化棋盘

3.打印棋盘,设计一个函数打印棋盘

Displayboard(board,ROW,COL);//打印棋盘

 

4.1.玩家下棋,玩家输入信息

4.2.电脑下棋,电脑自动输入信息

PlayerMove(board,ROW,COL);//玩家下棋

ComputerMove(board,ROW,COL);

5.判断棋局输赢情况

这里我们可以去思考,我们可以设计一个函数去判断,首先我们知道,玩家下棋是‘*’,电脑下棋是‘#’,就可以让函数返回‘*’,‘#’分别代表玩家赢和电脑赢,除此之外,我们还应该考虑两种情况,平局和游戏继续,这里就设计返回‘Q’,‘C’来表示平局和游戏继续

三.游戏实现的详细代码

main.c文件:

1. #include "game.h"
2. void menu()
3. {
4. printf("******************************\n");
5. printf("*            1.play          *\n");
6. printf("*            0.exit          *\n");
7. printf("******************************\n");
8. 
9. }
10. void game()
11. {
12. char count={0};
13. char board[ROW][COL];//创建棋盘
14. Initboard(board,ROW,COL);//初始化棋盘
15. Displayboard(board,ROW,COL);//打印棋盘
16. while(1)//循环是为了一直下棋,直到一方赢或着棋盘满了
17.     {
18. PlayerMove(board,ROW,COL);//玩家下棋
19. Displayboard(board,ROW,COL);
20.         count=Iswin(board,ROW,COL);//判断棋局情况
21. if(count!='C')//如果返回的是‘C’则棋盘还有空余且没有一方胜出
22.         {
23. break;
24.         }
25. ComputerMove(board,ROW,COL);
26. Displayboard(board,ROW,COL);
27.         count=Iswin(board,ROW,COL);
28. if(count!='C')
29.         {
30. break;
31.         }
32.     }
33. if(count=='*')//如果返回的是‘*’则是玩家赢
34.     {
35. printf("玩家赢\n");
36.     }
37. else if(count=='#')//如果返回的是‘#’则是电脑赢
38.     {
39. printf("电脑赢\n");
40.     }
41. if(count=='Q')//如果返回的是‘Q’则是平局
42.     {
43. printf("平局\n");
44.     }
45. }
46. int main()
47. {
48. srand((unsigned int)time(NULL));//控制随机变量更加自然
49. int input=0;
50. do
51.     {
52. menu();//菜单
53. printf("请选择\n");
54. scanf("%d",&input);
55. switch(input)
56.         {
57. case 1:
58. game();
59. break;
60. case 0:
61. printf("退出游戏\n");
62. break;
63. default:
64. printf("输入非法,重新选择\n");
65. break;
66.         }
67.     }while(input);
68. return 0;
69. }

game.c文件:

1. #include "game.h"
2. void  Initboard(char board[ROW][COL],int row,int col)
3. {
4. int i=0,j=0;
5. for(i=0;i<row;i++)
6.     {
7. for(j=0;j<col;j++)
8.         {
9.             board[i][j]=' ';//三字棋,一共9个格子,将这9个格子初始化为空格‘ ’
10.         }
11.     }
12. }
13. void Displayboard(char board[ROW][COL],int row,int col)
14. {
15. printf("*************三字棋*****************\n");
16. int i=0,j=0;
17. for(i=0;i<row;i++)
18.     {
19. for(j=0;j<col;j++)
20.         {
21. printf(" %c ",board[i][j]);
22. if(j<col-1)
23.             {
24. printf("|");
25.             }
26.         }
27. printf("\n");
28. if(i<row-1)
29.         {
30. for(j=0;j<col;j++)
31.             {
32. printf("---");
33. if(j<col-1)
34.                 {
35. printf("|");
36.                 }
37.             }
38. printf("\n");
39.         }
40.     }
41. printf("*************三字棋*****************\n");
42. }
43. void  PlayerMove(char board[ROW][COL],int row,int col)
44. {
45. printf("玩家下棋:>\n");
46. int x=0,y=0;
47. while(1)
48.     {
49. printf("输入下棋坐标\n");
50. scanf("%d %d",&x,&y);
51. if(x>=1&&x<=row&&y>=1&&y<=col)
52.         {
53. if(board[x-1][y-1]==' ')
54.             {
55.                 board[x-1][y-1]='*';
56. break;
57.             }
58. else
59.             {
60. printf("该坐标被占用,请重新输入\n");
61.             }
62.         }
63. else
64.         {
65. printf("输入不合法,重新输入\n");
66.         }
67.     }
68. }
69. void ComputerMove(char board[ROW][COL],int row,int col)
70. {
71. printf("电脑下棋:>\n");
72. int x=0,y=0;
73. while(1)
74.     {
75.         x=rand()%row;
76.         y=rand()%col;
77. if(board[x][y]==' ')
78.         {
79.             board[x][y]='#';
80. break;
81.         }
82.     }
83. }
84. int Judge(char board[ROW][COL],int row,int col)//判断是否有空余
85. {
86. int i=0,j=0;
87. for(i=0;i<row;i++)
88.     {
89. for(j=0;j<col;j++)
90.         {
91. if(board[i][j]==' ')
92.             {
93. return 1;
94.             }
95.         }
96.     }
97. return -1;
98. }
99. char Iswin(char board[ROW][COL],int row,int col)
100. {
101. int i=0;
102. for(i=0;i<row;i++)
103.     {
104. if(board[i][0]==board[i][1]&&board[i][1]==board[i][2]&&board[i][1]!=' ')//判断行是否相等
105.         {
106. return board[i][1];
107.         }
108.     }
109. for(i=0;i<row;i++)
110.     {
111. if(board[0][i]==board[1][i]&&board[1][i]==board[2][i]&&board[1][i]!=' ')//判断列是否相等
112.         {
113. return board[1][i];
114.         }
115.     }
116. if(board[0][0]==board[1][1]&&board[1][1]==board[2][2]&&board[1][1]!=' ')//判断对角线是否相等
117.     {
118. return board[1][1];
119.     }
120. if(board[0][2]==board[1][1]&&board[1][1]==board[2][0]&&board[1][1]!=' ')//判断对角线是否相等
121.     {
122. return board[1][1];
123.     }
124. int ret=Judge(board,row,col);//判断棋盘是否有空余
125. if(ret==1)//有空余就返回‘C’
126.     {
127. return 'C';
128.     }
129. else
130.     {
131. return 'Q';//没有空余就返回‘Q’平局
132.     }
133. }

game.h文件:

1. #ifndef game_h
2. #define game_h
3. #endif
4. 
5. //头文件
6. #include <stdio.h>
7. #include<stdlib.h>//控制随机变量的头文件
8. #include<time.h>//控制随机变量的头文件
9. 
10. //定义行列长度,这里是三字棋,应该定义为3
11. #define ROW 3
12. #define COL 3
13. 
14. void  Initboard(char board[ROW][COL],int row,int col);//初始化
15. void Displayboard(char board[ROW][COL],int row,int col);//打印棋盘
16. void  PlayerMove(char board[ROW][COL],int row,int col);//玩家下棋
17. void ComputerMove(char board[ROW][COL],int row,int col);//电脑下棋
18. char Iswin(char board[ROW][COL],int row,int col);//判断棋局情况

四.游戏成功运行的结果

BBA0299B-E882-4146-ABA2-7F4AD3B25BC9.png

B38BCA45-844B-441B-BFFC-DD26907EC46E.png

注:我使用的编译器是xcode(mac版本的)

五. 游戏细节补充

大家可以设置一个用户登陆过程,即是输入正确的密码才能进入游戏,让我们来看看

1. int main()
2. {
3. int count=0;
4. char arr[]="bit.is.good999";
5. char brr[20]={0};
6. while(count<3)
7.     {
8. printf("请输入密码:>\n");
9. scanf("%s",brr);
10. if(strcmp(arr,brr)==0)
11.         {
12. printf("密码输入正确,正在加载游戏\n");
13. srand((unsigned int)time(NULL));//控制随机变量更加自然
14. int input=0;
15. do
16.             {
17. menu();//菜单
18. printf("请选择\n");
19. scanf("%d",&input);
20. switch(input)
21.                 {
22. case 1:
23. game();
24. break;
25. case 0:
26. printf("退出游戏\n");
27. break;
28. default:
29. printf("输入非法,重新选择\n");
30. break;
31.                 }
32.             }while(input);
33. if(input==0)
34.             {
35. break;
36.             }
37.         }
38. else
39.         {
40. printf("密码输入错误,错误三次将退出登陆--------%d次\n",count+1);
41.             count++;
42.         }
43.     }
44. return 0;
45. }

运行结果:B72ED4B4-BD50-4247-8C8F-D27DAF324F58.png其实这个用户登录过程,可以广范适用于其他的游戏,大家可以去尝试一下

注: 使用字符串比较函数时strcmp,不要忘记引头文件#include<string.h>

六.心得

这个三字棋看似生活不起眼的小游戏,但是对于像我一样才开始接触C的人来说,实现起来也不是那样轻而易举。实现三字棋的过程,让我明白掌握代码并非最重要的,最重要的是,理清实现功能的逻辑,例如:实现这个游戏时,首先得了解游戏规则,其次需要一个棋盘......只要自己逻辑清晰,写代码也是水到渠成,还有一点,只要自己掌握逻辑,下次想再次实现这个功能或着分析已写的代码就不会犯怵了。最后我们要多善于整理总结,下次我们遇到类似的问题,就可以触类旁通了。



相关文章
|
9月前
|
C语言
C语言游戏——三字棋
C语言游戏——三字棋
86 0
|
C语言
【C语言】小游戏-三字棋
【C语言】小游戏-三字棋
75 0
|
C语言
C语言实现三字棋~步骤详解与代码
C语言实现三字棋~步骤详解与代码
150 0
C语言实现三字棋~步骤详解与代码
|
存储 C语言 容器
【c语言】 我使用c语言基础做了一个老少皆宜的”国民小游戏(三字棋)“
本三字棋小游戏是依靠二维数组为核心来实现的,可以更加好理解掌握c语言数组的概念知识,依靠做小游戏项目,把学到了知识在输出出来加已巩固,最后有源代码
188 0
|
1月前
|
存储 算法 C语言
【C语言程序设计——函数】素数判定(头歌实践教学平台习题)【合集】
本内容介绍了编写一个判断素数的子函数的任务,涵盖循环控制与跳转语句、算术运算符(%)、以及素数的概念。任务要求在主函数中输入整数并输出是否为素数的信息。相关知识包括 `for` 和 `while` 循环、`break` 和 `continue` 语句、取余运算符 `%` 的使用及素数定义、分布规律和应用场景。编程要求根据提示补充代码,测试说明提供了输入输出示例,最后给出通关代码和测试结果。 任务核心:编写判断素数的子函数并在主函数中调用,涉及循环结构和条件判断。
62 23
|
1月前
|
算法 C语言
【C语言程序设计——函数】利用函数求解最大公约数和最小公倍数(头歌实践教学平台习题)【合集】
本文档介绍了如何编写两个子函数,分别求任意两个整数的最大公约数和最小公倍数。内容涵盖循环控制与跳转语句的使用、最大公约数的求法(包括辗转相除法和更相减损术),以及基于最大公约数求最小公倍数的方法。通过示例代码和测试说明,帮助读者理解和实现相关算法。最终提供了完整的通关代码及测试结果,确保编程任务的成功完成。
67 15
|
1月前
|
C语言
【C语言程序设计——函数】亲密数判定(头歌实践教学平台习题)【合集】
本文介绍了通过编程实现打印3000以内的全部亲密数的任务。主要内容包括: 1. **任务描述**:实现函数打印3000以内的全部亲密数。 2. **相关知识**: - 循环控制和跳转语句(for、while循环,break、continue语句)的使用。 - 亲密数的概念及历史背景。 - 判断亲密数的方法:计算数A的因子和存于B,再计算B的因子和存于sum,最后比较sum与A是否相等。 3. **编程要求**:根据提示在指定区域内补充代码。 4. **测试说明**:平台对代码进行测试,预期输出如220和284是一组亲密数。 5. **通关代码**:提供了完整的C语言代码实现
60 24
|
1月前
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
63 16
|
1月前
|
存储 编译器 C语言
【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
36 3