提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
本篇为用C语言实现三子棋,主要时熟悉C语言的函数和循环,重点在功能实现的逻辑。
一、创建阶段
项目比较简单,我们在VS_CODE里面,在自己的项目文件夹下,创建SZQ_main.c文件,用于实现主体的功能和函数的实现,再定义一个SZQ_main.h文件,用于存放此项目所用到的所有头文件,以及函数的声明。
二、主要步骤
1.先把菜单打印出来
我们玩游戏一般是有个选择的菜单,可以选择玩和不玩。先确认是否进入游戏,选择1,进入;选择0,退出;选择其他数字,则显示输入错误。此处需要用到while循环和switch语句。
代码如下:
void menu(){
printf("**************************************\n");
printf("*************1,play 0,exit***********\n");
printf("**************************************\n");
}
int main(){
//srand((unsigned int )time(NULL)); //设置随机数的生成起点
int input =0;
do {
menu();
printf("请选择:");
scanf("%d",&input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误");
break;
}
}while (input);
return 0;
}
2.主体框架搭建和实现
1,先把三子棋的板子先弄出来
用户选择1后开始游戏,这时我们就要把棋盘打印出来,这个棋盘由棋子和格子构成。这里的棋子,我们要定义一个二维数组,大家观察下面的棋盘,会发现初始化的棋盘没有棋子,其实,这里的棋子被初始化为空格。
代码如下
注意:这里我预先在SZQ_main.h里面给行和列进行了宏定义,方便以后进行修改,以及函数声明:
#ifndef _SZQ_MAIN_H_
#define _SZQ_MAIN_H_
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL],int row,int col);
void DisplayBoard(char board[ROW][COL],int row,int col);
void PlauerMove(char board[ROW][COL],int row,int col);
void ComputerMove(char board[ROW][COL],int row,int col);
char IsWin(char board[ROW][COL],int row,int col);
int IsFull(char board[ROW][COL],int row,int col);
#endif
函数主体代码如下,先给棋盘初始化成空格,然后再打印出来:
void InitBoard(char board[ROW][COL],int row,int col){
int i=0;
int j=0;
for(i=0;i<row;i++){
for(j=0;j<col;j++){
board[i][j]= ' ';
}
}
}
void DisplayBoard(char board[ROW][COL],int row,int col){
int i=0;
for(int i=0;i<row;i++){
// printf(" %c | %c | %c \n",board[i][0], board[i][1],board[i][2]);
int j=0;
for(j=0;j<col;j++){
printf(" %c ",board[i][j]);
if(j<col-1){
printf("|");
}
}
printf("\n");
if(i<row-1){
int j=0;
for(j=0;j<col;j++){
//printf("---|---|---\n");
printf("---");
if(j<col-1)
printf("|");
}
printf("\n");
}
}
}
2.玩家下棋和电脑下棋的实现
玩家手动输入所选的坐标,电脑自动选择位置。
关于玩家部分,我们根据用它关乎输入的坐标,由于我们的棋盘数组是从9开始的吗,所以,我们要在将棋盘打印出用户下棋子的情况,需要用户输入的坐标x和y都减去1。代码实现如下:
//玩家下棋
void PlayerMove(char board[ROW][COL],int row,int col){
int x=0;
int y=0;
printf("玩家请下棋:");
while (1)
{
printf("玩家请输入坐标:");
scanf("%d %d",&x,&y);
//合法坐标
if(x>=1 && x<=row && y>=1 && y <=col){
if(board[x-1][y-1]==' '){
board[x-1][y-1]='*';
break;
}
else{
printf("坐标已经被占用,不能下棋,请选择其他位置:");
}
}
else{
printf("非法坐标!重新数输入:");
}
}
}
关于电脑端部分,我们电脑下的棋用‘#’显示。此处要用到rand()函数,rand()函数为电脑获取随机的一个大于0的整数,因为电脑选择的坐标范围是0~2,需要x=rand()%3来实现,因为任意一个整数对3取余数,就只有0,1,2的可能。为保证每次选择的坐标不同,需要在主函数添加srand((unsigned int)time(NULL));这个代码是时间戳,保证每个时刻获取的坐标不同。这里需要<stdlib.h>以及<time.h>头文件。当然这样的好处是方便,但是不够人心性化,我们也可以采用堵玩家下棋的方式来模拟电脑下棋,这个需要自己去实现。
代码实现如下:
void ComputerMove(char board[ROW][COL],int row,int col){
printf("电脑下棋->\n");
int x=0;
int y=0;
while (1)
{
x=rand()%row;//0-2
y=rand()%col;//0-2
if(board[x][y]==' '){
board[x][y]='#';
break;
}/* code */
}
}
3.判断胜负
我们需要判断出到底是谁赢了,或者是不是平局了。若有一方一行,一列,一条对角线连成一条线,则此方胜利,若棋盘已满,但没有胜负,则平局。
关于以下函数的返回值,玩家赢,返回‘*’;电脑赢,返回‘#’;平局,返回‘Q’;否则,游戏继续,返回‘C’。
代码实现如下:
char IsWin(char board[ROW][COL],int row,int col){
//hang
int i=0;
for(i=0;i<row;i++){
if(board[i][0]==board[i][1]&&board[i][1]==board[i][2]&&board[i][1]!=' '){
return board[i][1];
}
}
//lie
int j=0;
for(j=0;i<col;j++){
if(board[0][j]==board[1][j] &&board[1][j]==board[2][j]&&board[1][j]!=' '){
return board[1][j];
}
}
//duijiaoxian
if(board[0][0]==board[1][1]&&board[1][1]==board[2][2]&&board[1][1]!=' '){
return board[0][0];
}
if(board[0][2]==board[1][1]&&board[1][1]==board[2][0]&&board[1][1]!=' '){
return board[0][2];
}
//
if(IsFull(board,row,col)){
return 'Q';
}
return 'C';
}
此处我们添加一个判断棋盘是否已满的函数IsFull();
//满了返回1,否为0
int IsFull(char board[ROW][COL],int row,int col){
int i;
for(i=0;i<row;i++){
for(int j=0;j<col;j++){
if(board[i][j]==' ')
{return 0;}
}
}
return 1;
}
完整代码如下:
SZQ_main.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include"SZQ_main.h"
//玩家下棋
void PlayerMove(char board[ROW][COL],int row,int col){
int x=0;
int y=0;
printf("玩家请下棋:");
while (1)
{
printf("玩家请输入坐标:");
scanf("%d %d",&x,&y);
//合法坐标
if(x>=1 && x<=row && y>=1 && y <=col){
if(board[x-1][y-1]==' '){
board[x-1][y-1]='*';
break;
}
else{
printf("坐标已经被占用,不能下棋,请选择其他位置:");
}
}
else{
printf("非法坐标!重新数输入:");
}
}
}
void ComputerMove(char board[ROW][COL],int row,int col){
printf("电脑下棋->\n");
int x=0;
int y=0;
while (1)
{
x=rand()%row;//0-2
y=rand()%col;//0-2
if(board[x][y]==' '){
board[x][y]='#';
break;
}/* code */
}
}
void InitBoard(char board[ROW][COL],int row,int col){
int i=0;
int j=0;
for(i=0;i<row;i++){
for(j=0;j<col;j++){
board[i][j]= ' ';
}
}
}
void DisplayBoard(char board[ROW][COL],int row,int col){
int i=0;
for(int i=0;i<row;i++){
// printf(" %c | %c | %c \n",board[i][0], board[i][1],board[i][2]);
int j=0;
for(j=0;j<col;j++){
printf(" %c ",board[i][j]);
if(j<col-1){
printf("|");
}
}
printf("\n");
if(i<row-1){
int j=0;
for(j=0;j<col;j++){
//printf("---|---|---\n");
printf("---");
if(j<col-1)
printf("|");
}
printf("\n");
}
}
}
char IsWin(char board[ROW][COL],int row,int col){
//hang
int i=0;
for(i=0;i<row;i++){
if(board[i][0]==board[i][1]&&board[i][1]==board[i][2]&&board[i][1]!=' '){
return board[i][1];
}
}
//lie
int j=0;
for(j=0;i<col;j++){
if(board[0][j]==board[1][j] &&board[1][j]==board[2][j]&&board[1][j]!=' '){
return board[1][j];
}
}
//duijiaoxian
if(board[0][0]==board[1][1]&&board[1][1]==board[2][2]&&board[1][1]!=' '){
return board[0][0];
}
if(board[0][2]==board[1][1]&&board[1][1]==board[2][0]&&board[1][1]!=' '){
return board[0][2];
}
//
if(IsFull(board,row,col)){
return 'Q';
}
return 'C';
}
//满了返回1,否为0
int IsFull(char board[ROW][COL],int row,int col){
int i;
for(i=0;i<row;i++){
for(int j=0;j<col;j++){
if(board[i][j]==' ')
{return 0;}
}
}
return 1;
}
void game(){
char ret =0;
char board[ROW][COL]={0};
//初始化棋盘函数
InitBoard(board,ROW,COL);
DisplayBoard(board,ROW,COL);
//玩家下棋
while (1)
{
PlayerMove(board,ROW,COL);
ret=IsWin(board,ROW,COL);
if(ret !='C'){
break;
}
DisplayBoard(board,ROW,COL);
//判断是否赢了
ComputerMove(board,ROW,COL);
ret=IsWin(board,ROW,COL);
if(ret !='C'){
break;
}
DisplayBoard(board,ROW,COL);
}
if(ret == '*'){
printf("玩家赢了!\n");
}
else if(ret == '#'){
printf("电脑赢了!\n");
}
else {
printf("平局!\n");
}
DisplayBoard(board,ROW,COL);
}
void menu(){
printf("**************************************\n");
printf("*************1,play 0,exit***********\n");
printf("**************************************\n");
}
int main(){
srand((unsigned int )time(NULL)); //设置随机数的生成起点
int input =0;
do {
menu();
printf("请选择:");
scanf("%d",&input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误");
break;
}
}while (input);
return 0;
}
SZQ_main.h
```c
在这里插入代码#ifndef _SZQ_MAIN_H_
#define _SZQ_MAIN_H_
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL],int row,int col);
void DisplayBoard(char board[ROW][COL],int row,int col);
void PlauerMove(char board[ROW][COL],int row,int col);
void ComputerMove(char board[ROW][COL],int row,int col);
char IsWin(char board[ROW][COL],int row,int col);
int IsFull(char board[ROW][COL],int row,int col);
#endif
片
# 总结
关于电脑下棋部分还可以自己多家修改,使其更加智能。这个项目主要是锻炼大家基本的函数调用,以及对数组的理解。