三子棋游戏(超级详解,附加电脑下棋优化)

目录

前言

一,游戏规则

二,游戏步骤

三,游戏实现

3.1游戏构思和框架

3.2 棋盘的初始化和打印

3.3 玩家和电脑下棋的实现

3.4 判断输赢

3.5 游戏平局

3.6 游戏头文件game.h

四,电脑下棋优化

五,游戏总代码


前言

继上一次的猜数字小游戏以后,我们再来个更加锻炼一个逻辑的游戏,这个游戏比上个代码多,但很能考验我们的逻辑能力。逻辑能力上来了,以后做项目,编写程序的时候就不会太吃力。话不多说,先来一张美图,直接开始。

 

一,游戏规则

跟小时候在作业本上画个“井”子格一样,谁先连成一条线谁赢。如果棋盘满了还没有分出胜负,则平局。只不过这次在电脑上和人机下棋,在电脑上显示“井”子格。这次玩家棋子用“ # ”表示,电脑用“ * ”表示。

 

二,游戏步骤

游戏的步骤如下:

第一步,玩家下棋

第二步,电脑下棋

第三步,如果没分出胜负重复1,2步骤,一旦有一方胜利就终止游戏。

另外还要注意的是:

1,在游戏步骤执行之前,我们想一下,在开始之前应该有一个菜单,来满足我们是否要选择玩游戏。而游戏结束之后应该跳到菜单界面,由玩家选择是否还要玩游戏。

2,在执行游戏步骤的时候,玩家和电脑下棋之后到要进行判断输赢。

3,三子棋总共有九格,那三子棋的实现就应该是用3*3二维数组来实现,每一个格子放一个数。更何况我们不能直接在屏幕上来下,我们可以用坐标来代替,而二维数组正好可以满足要求。

三,游戏实现

3.1游戏构思和框架

这次我们把这个游戏分别放在不同的文件中,游戏框架放在test.c源文件中,游戏实现放在game.c源文件中,函数声明放在game.h头文件中。

我们现在头文件里添加个库函数<stdio.h>,然后把3分别赋值给ROW,LOW这样做是为了以后要是写四子棋,五子棋时只用修改ROW和LOW赋的值就行了。

//game.h
#include<stdio.h>
#defile ROW 3
#defile COL 3

然后我们将头文件test.h作为test.c的库函数(这样就相当于直接调用test.h里的内容了)和游戏框架如下所示:

//test.c
#include"game.h"

void mune()
{
	printf("******************************\n");
	printf("******** 1.开始游戏 **********\n");
	printf("******** 0.退出游戏 **********\n");
	printf("******************************\n");
}

int main()
{
	int input = 0;
    srand((unsigned)time(NULL));    //随机数的起点,后面会提到
	do
	{
		mune();//打印游戏菜单
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		default:
			printf("选择错误,重新选择。\n");
			break;
		}
	} while (input);

	return 0;


}

用do...while()语句来实现整个框架,先把菜单打印出来,然后看着菜单进行选择,将选项赋值在变量input中,然后再用switch语句来执行不同的选项,将游戏实现的过程放在game() 函数中。

然后接下来我们开始编写game() 函数。

根据构思我们可以想出以下步骤:

1,屏幕出现棋盘。

2,玩家输入坐标下棋,判断输赢,没赢继续执行下一步。

3,电脑下棋,判断输赢,没赢执行第1步。

3.2 棋盘的初始化和打印

既然出现棋盘,那我们就先创建一个3*3棋盘,并对棋盘进行初始化(让棋盘里的内容都变成空格)。然后打印棋盘:

//test.c
void game()
{
	char chessboard[ROW][COL];//创建一个3*3的棋盘
	init_chessboard(chessboard, ROW, COL);//初始化棋盘
    print_chessboard(chessboard, ROW, COL);//打印棋盘
}

我们将棋盘的初始化和打印棋盘的实现放在game.c文件中,game.c中也一样将game.h作为库函数调用。

//game.c
#include "game.h"
void init_chessboard(char chessboard[ROW][COL],int row,int col)//初始化棋盘
{
    int i,j;
    for(i = 0;i < row; i++)
    {
        for(j = 0; j < col; j++)
        {
            chessboard[i][j] = ' '; //先将棋盘中的数打印成空格
        }
    }
    
}
void print_chessboard(char chessboard[ROW][COL],int row,int col)//打印棋盘
{
    int i,j;
    for(i = 0; i < row; i++)       //运行三次后,打印棋盘
    {
        for(j = 0; j < col; j++)    //运行三次后: %c | %c | %c 
            {
                if(j == col - 1)
                    printf(" %c ", chessboard[i][j]);
                else
                    printf(" %c |", chessboard[i][j]);
            }
        printf("\n");
        for(j = 0; j < col; j++)    //运行三次后: ---|---|---
            {
               if(i < 2)
                    {
                        if(j == col - 1)
                            printf("---");
                        else
                         printf("---|");
                    }
            }
        printf("\n");
      }          
}

3.3 玩家和电脑下棋的实现

当屏幕上打印棋盘后,玩家该输入坐标下棋。玩家下棋用‘#’表示,电脑下棋用‘*’表示

//test.c
void game()
{
	char chessboard[3][3];                     //创建一个3*3的棋盘
	init_chessboard(chessboard, ROW, COL);         //初始化棋盘
    print_chessboard(chessboard, ROW, COL);        //打印棋盘
	player_playchess(chessboard, ROW, COL);       //玩家下棋
    judge(chessboard, ROW, COL);                    //判断输赢
	computer_playchess(chessboard, ROW, COL);     //电脑下棋

}

在game.c中实现玩家和电脑下棋的操作。其中玩家下棋是输入坐标下棋,电脑是靠rand()来生成随机数来下棋。然后在test.c中加一个随机起点(srand((unsigned)time(NULL)))(具体rand()生成随机数可以看这篇的生成随机值)

如下:

//game.c
void player_playchess(char chessboard[ROW][COL],int row,int col)
{
    
    int input = 1;
    while(input)
    {
        printf("请输入下棋的坐标\n");
        int a = 0;                                        //创建a,b两个变量来储存坐标
        int b = 0;
        scanf("%d %d",&a,&b);
        if(a > 0 && a < row + 1 && b > 0 && b < col + 1)    //坐标必须在0到row(col)+1之间
        {
            if(chessboard[a - 1][b - 1] == ' ')              //判断输入坐标的地方是否为空格
                {
                    chessboard[a - 1][b - 1] = '#';
                    input = 0;
                 }
            else 
                printf("该坐标已被占用,请从新输入");
        }
        else
        {
            printf("坐标非法,请重新输入");
        }
    }
    print_chessboard(chessboard,row,col);       //打印下棋后的棋盘
    
}
//电脑下棋
void computer_playchess(int chessboard[ROW][COL], int row, int col)
{
    int input = 1;
    while(input)
    {  
             int a = rand() % row;    //用a,b装 0到2 的随机数
             int b = rand() % col;
             if(chessboard[a - 1][b - 1] == ' ')              //判断输入坐标的地方是否为空格
                {
                    chessboard[a - 1][b - 1] = '*';
                    input = 0;
                 }
    } 
    print_chessboard(chessboard,row,col);       //打印下棋后的棋盘     
}

3.4 判断输赢

在电脑和玩家下棋后要判断输赢,如果平局,返回‘Q’,如果都没有赢,就返回 'P',游戏继续。

//game.c


char judge(int chessboard[ROW][COL],int row,int col)
{
    int i = 0;
    for(i = 0; i < row; i++)
    {
        if(chessboard[i][0] == chessboard[i][1] && chessboard[i][1] == chessboard[i][2] 
 && chessboard[i][0] != ' ')
        {
            return chessboard[i][0];    //判断一行是否相同
        }
        if(chessboard[0][i] == chessboard[1][i] && chessboard[1][i] == chessboard[2][i] && chessboard[0][i] != ' ')
        {
            return chessboard[0][i];    //判断一列是否相同
        }
    }
        if(chessboard[0][0] == chessboard[1][1] && chessboard[1][1] == chessboard[2][2] && chessboard[0][0] != ' ')
        {
            return chessboard[0][0];   //判断右斜线是否相同
        }   
         if(chessboard[0][2] == chessboard[1][1] && chessboard[1][1] == chessboard[2][0] && chessboard[1][1] != ' ')
        {
            return chessboard[0][2];    //判断左斜线是否相同
        }
    if(if_full(chessboard,row,col)) //判断是否平局,平局返回‘Q’
        {
            return 'Q';
        } 
    
    
    return 'P';
    
}

与电脑下棋一来一回后,棋盘还未满,加一个while循环。如下

//test.c
void game()
{
    int char = 0;            //装判断函数的返回值
	char chessboard[3][3];                     //创建一个3*3的棋盘
	init_chessboard(chessboard, ROW, COL);         //初始化棋盘
    print_chessboard(chessboard, ROW, COL);        //打印棋盘
    while(1)                            
    {
	player_playchess(chessboard, ROW, COL);               //玩家下棋
    ret = judge(chessboard, ROW, COL);                    //判断输赢
    if( ret != 'P')                                         //judge函数返回'P',游戏继续
    {
        break;
    } 
	computer_playchess(chessboard, ROW, COL);             //电脑下棋
    ret = judge(chessboard, ROW, COL);                    //判断输赢
    if( ret != 'P')
    {
        break;
    }                  
}

3.5 游戏平局

如果三子棋棋盘都满了,并且还没分出胜负,游戏就平局。if_full判断棋盘是否满了,如全满返回1,然后在前面judge函数中返回'Q',来表示平局。

//game.c
int  if_full(int chessboard[ROW][COL],int row,int col)       
{
    int i = 0;
    for(i = 0; i < row; i++)
    {
        int j = 0;
        for(j = 0; j < col; j++)
        {
            if(chessboard[i][j] == ' ')
                return 0;              //遍历一遍是否有空格,有返回0
        }
     }
    return '1';    //如果棋盘都没有空格,返回‘1’
}

接着如果将judge返回值放在ret中,如果ret == '#',玩家胜利。如果ret == ' * ',电脑胜利。如果ret == 'Q',游戏平局。代码如下:

//test.c
void game()
{
    char ret = 0;                                //装判断输赢函数的返回值
	char chessboard[3][3];                     //创建一个3*3的棋盘
	init_chessboard(chessboard, ROW, COL);         //初始化棋盘
    print_chessboard(chessboard, ROW, COL);        //打印棋盘
    while(1)                            
    {
	player_playchess(chessboard, ROW, COL);               //玩家下棋
    ret = judge(chessboard, ROW, COL);                    //判断输赢
    if( ret != 'P')                                         //judge函数返回'P',游戏继续
    {
        break;
    } 
	computer_playchess(chessboard, ROW, COL);             //电脑下棋
    ret = judge(chessboard, ROW, COL);                    //判断输赢
    if( ret != 'P')
    {
        break;
    }   
    }               
    if(ret == '#')
    {
        printf("玩家胜利!");
    }
    if(ret == '*')
    {
        printf("电脑胜利!");
    }
    if(ret == 'Q')
    {
        printf("游戏平局");
    }
    print_chessboard(chessboard, ROW, COL);        //游戏结束再打印一下打印棋盘
}
    

3.6 游戏头文件game.h

将game.c源文件中代码的实现通过game.h头文件与test.c源文件进行联系。

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 3
#define COL 3
void init_chessboard(chessboard[ROW][COL], int ROW, int COL);
void print_chessboard(chessboard[ROW][COL], int ROW, int COL);
void player_playchess(chessboard[ROW][COL], int ROW, int COL);
void computer_playchess(chessboard[ROW][COL], int ROW, int COL);
void judge(chessboard[ROW][COL], int ROW, int COL); 

四,电脑下棋优化

前面的电脑下棋太菜了,这次我们用代码提高电脑下棋水平。从而让“人工智障”变为“人工智能”。

我们需要电脑来“拦截”我们的棋子,当我们有两个棋子相连的时候三子棋,就要进行拦截了。否则,电脑随机下棋。实现代码如下:

int intell_computer(char chessboard[ROW][COL], int row, int col)
{
    int i = 0;
    //行判断
    for (i = 0; i < row; i++)
    {
        if (chessboard[i][0] == chessboard[i][1] && chessboard[i][2] == ' ')
        {
            chessboard[i][2] = '*';
            return 1;
        }
        if (chessboard[i][0] == chessboard[i][2] && chessboard[i][1] == ' ')
        {
            chessboard[i][1] = '*';
            return 1;
        }
        if (chessboard[i][1] == chessboard[i][2] && chessboard[i][0] == ' ')
        {
            chessboard[i][0] = '*';
            return 1;
        }
    }
    //列判断
    for (i = 0; i < col; i++)
    {
        if (chessboard[0][i] == chessboard[1][i] && chessboard[2][i] == ' ')
        {
            chessboard[2][i] = '*';
            return 1;
        }
        if (chessboard[0][i] == chessboard[2][i] && chessboard[1][i] == ' ')
        {
            chessboard[1][i] = '*';
            return 1;
        }
        if (chessboard[1][i] == chessboard[2][i] && chessboard[0][i] == ' ')
        {
            chessboard[0][i] = '*';
            return 1;
        }
    }
    //对角线判断
    if (chessboard[1][1] == chessboard[0][0] && chessboard[2][2] == ' ')
    {
        chessboard[2][2] = '*';
        return 1;
    }
    if (chessboard[0][0] == chessboard[2][2] && chessboard[1][1] == ' ')
    {
        chessboard[1][1] = '*';
        return 1;
    }
    if (chessboard[1][1] == chessboard[2][2] && chessboard[0][0] == ' ')
    {
        chessboard[0][0] = '*';
        return 1;
    }
    //斜对角线判断
    if (chessboard[1][2] == chessboard[2][1] && chessboard[3][0] == ' ')
    {
        chessboard[3][i] = '*';
        return 1;
    }
    if (chessboard[1][2] == chessboard[3][0] && chessboard[2][1] == ' ')
    {
        chessboard[2][1] = '*';
        return 1;
    }
    if (chessboard[2][1] == chessboard[3][0] && chessboard[1][2] == ' ')
    {
        chessboard[1][2] = '*';
        return 1;
    }
    return 0;
}

我们把这代码插入computer_playchess的实现里,代码如下:

    //电脑下棋
    void computer_playchess(char chessboard[ROW][COL], int row, int col)
    {
        printf("电脑下棋\n");
        if (intell_computer(chessboard, row, col)) //判断是否复合拦截条件,复合进行拦截。
        {
            ;
        }
        else
        {
            while (1)
            {
                int a = rand() % row;    //用a,b装 0到2 的随机数
                int b = rand() % col;
                if (chessboard[a][b] == ' ')              //判断输入坐标的地方是否为空格
                {
                    chessboard[a][b] = '*';
                    break;
                }
            }
        }
        print_chessboard(chessboard,row,col);       //打印下棋后的棋盘     
    }

五,游戏总代码

//game.h

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 3
#define COL 3
void init_chessboard(chessboard[ROW][COL], int ROW, int COL);
void print_chessboard(chessboard[ROW][COL], int ROW, int COL);
void player_playchess(chessboard[ROW][COL], int ROW, int COL);
void computer_playchess(chessboard[ROW][COL], int ROW, int COL);
void judge(chessboard[ROW][COL], int ROW, int COL); 

//test.c

//test.c
#include"game.h"

void mune()
{
	printf("******************************\n");
	printf("******** 1.开始游戏 **********\n");
	printf("******** 0.退出游戏 **********\n");
	printf("******************************\n");
}
void game()
{
	char ret = 0;
	char chessboard[3][3] = { 0 };                     //创建一个3*3的棋盘
	init_chessboard(chessboard, ROW, COL);         //初始化棋盘
	system("cls");
	print_chessboard(chessboard, ROW, COL);        //打印棋盘
	while (1)
	{
		player_playchess(chessboard, ROW, COL);               //玩家下棋
		print_chessboard(chessboard, ROW, COL);       //打印下棋后的棋盘
		ret = judge(chessboard, ROW, COL);                    //判断输赢
		if (ret != 'P')                                         //judge函数返回'P',游戏继续
		{
			break;
		}
		computer_playchess(chessboard, ROW, COL);             //电脑下棋
		ret = judge(chessboard, ROW, COL);                    //判断输赢
		if (ret != 'P')
		{
			break;
		}
	}
	if (ret == '#')
	{
		printf("玩家胜利!\n");
	}
	if (ret == '*')
	{
		printf("电脑胜利!\n");
	}
	if (ret == 'Q')
	{
		printf("游戏平局\n");
	}
		
	print_chessboard(chessboard, ROW, COL);        //游戏结束再打印一下打印棋盘
}

int main()
{
	int input = 0;
	srand((unsigned)time(NULL));    //随机数的起点,后面会提到
		do
		{
			mune();//打印游戏菜单
			printf("请选择:");
			scanf("%d", &input);
			switch (input)
			{
			case 1:
				game();
				break;
			case 0:
				break;
			default:
				printf("选择错误,重新选择。\n");
				break;
			}
		} while (input);

		return 0;


}

//game.c

#include "game.h"
int intell_computer(char chessboard[ROW][COL], int row, int col)
{
    int i = 0;
    //行
    for (i = 0; i < row; i++)
    {
        if (chessboard[i][0] == chessboard[i][1] && chessboard[i][2] == ' ')
        {
            chessboard[i][2] = '*';
            return 1;
        }
        if (chessboard[i][0] == chessboard[i][2] && chessboard[i][1] == ' ')
        {
            chessboard[i][1] = '*';
            return 1;
        }
        if (chessboard[i][1] == chessboard[i][2] && chessboard[i][0] == ' ')
        {
            chessboard[i][0] = '*';
            return 1;
        }
    }
    //列
    for (i = 0; i < col; i++)
    {
        if (chessboard[0][i] == chessboard[1][i] && chessboard[2][i] == ' ')
        {
            chessboard[2][i] = '*';
            return 1;
        }
        if (chessboard[0][i] == chessboard[2][i] && chessboard[1][i] == ' ')
        {
            chessboard[1][i] = '*';
            return 1;
        }
        if (chessboard[1][i] == chessboard[2][i] && chessboard[0][i] == ' ')
        {
            chessboard[0][i] = '*';
            return 1;
        }
    }
    //对角线
    if (chessboard[1][1] == chessboard[0][0] && chessboard[2][2] == ' ')
    {
        chessboard[2][2] = '*';
        return 1;
    }
    if (chessboard[0][0] == chessboard[2][2] && chessboard[1][1] == ' ')
    {
        chessboard[1][1] = '*';
        return 1;
    }
    if (chessboard[1][1] == chessboard[2][2] && chessboard[0][0] == ' ')
    {
        chessboard[0][0] = '*';
        return 1;
    }
    //斜对角线
    if (chessboard[1][2] == chessboard[2][1] && chessboard[3][0] == ' ')
    {
        chessboard[3][i] = '*';
        return 1;
    }
    if (chessboard[1][2] == chessboard[3][0] && chessboard[2][1] == ' ')
    {
        chessboard[2][1] = '*';
        return 1;
    }
    if (chessboard[2][1] == chessboard[3][0] && chessboard[1][2] == ' ')
    {
        chessboard[1][2] = '*';
        return 1;
    }
    return 0;
}
void init_chessboard(char chessboard[ROW][COL],int row,int col)//初始化棋盘
{
    int i, j;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            chessboard[i][j] = ' '; //先将棋盘中的数打印成空格
        }
    }

}
void print_chessboard(char chessboard[ROW][COL], int row, int col)//打印棋盘
{
    int i, j;
    for (i = 0; i < row; i++)       //运行三次后,打印棋盘
    {
        for (j = 0; j < col; j++)    //运行三次后: %c | %c | %c 
        {
            if (j == col - 1)
                printf(" %c ", chessboard[i][j]);
            else
                printf(" %c |", chessboard[i][j]);
        }
        printf("\n");
        for (j = 0; j < col; j++)    //运行三次后: ---|---|---
        {
            if (i < row - 1)
            {
                if (j == col - 1)
                    printf("---");
                else
                    printf("---|");
            }
        }
        printf("\n");

    }
}
    //game.c
    void player_playchess(char chessboard[ROW][COL], int row, int col)
    {
        printf("玩家下棋\n");
        int a = 0;                                        //创建a,b两个变量来储存坐标
        int b = 0;
        while (1)
        {
            printf("请输入下棋的坐标\n");
            scanf("%d %d", &a, &b);
            if (a > 0 && a < row + 1 && b > 0 && b < col + 1)    //坐标必须在0到row(col)+1之间
            {
                if (chessboard[a - 1][b - 1] == ' ')              //判断输入坐标的地方是否为空格
                {
                    chessboard[a - 1][b - 1] = '#';
                    break;
                }
                else
                    printf("该坐标已被占用,请重新输入坐标\n");
            }
            else
            {
                printf("坐标非法,请重新输入\n");
            }
        }


    }


    //电脑下棋
    void computer_playchess(char chessboard[ROW][COL], int row, int col)
    {
        printf("电脑下棋\n");
        if (intell_computer(chessboard, row, col))
        {
            ;
        }
        else
        {
            while (1)
            {
                int a = rand() % row;    //用a,b装 0到2 的随机数
                int b = rand() % col;
                if (chessboard[a][b] == ' ')              //判断输入坐标的地方是否为空格
                {
                    chessboard[a][b] = '*';
                    break;
                }
            }
        }
        print_chessboard(chessboard,row,col);       //打印下棋后的棋盘     
    }
    static int  if_full(char chessboard[ROW][COL], int row, int col)
    {
        int i = 0;
        for (i = 0; i < row; i++)
        {
            int j = 0;
            for (j = 0; j < col; j++)
            {
                if (chessboard[i][j] == ' ')
                    return 0;              //遍历一遍是否有空格,有返回0
            }
        }
        return 1;    //如果棋盘都没有空格,返回‘1’
    }
    char judge(char chessboard[ROW][COL], int row, int col)
    {
        int i = 0;
        for (i = 0; i < row; i++)
        {
            if (chessboard[i][0] == chessboard[i][1] && chessboard[i][1] == chessboard[i][2] && chessboard[i][0] != ' ')
            {
                return chessboard[i][0];    //判断一行是否相同
            }
        }
        for (i = 0; i < row; i++)
        {
            if (chessboard[0][i] == chessboard[1][i] && chessboard[1][i] == chessboard[2][i] && chessboard[0][i] != ' ')
            {
                return chessboard[0][i];    //判断一列是否相同
            }
        }
        if (chessboard[0][0] == chessboard[1][1] && chessboard[1][1] == chessboard[2][2] && chessboard[0][0] != ' ')
        {
            return chessboard[0][0];   //判断右斜线是否相同
        }
        if (chessboard[0][2] == chessboard[1][1] && chessboard[1][1] == chessboard[2][0] && chessboard[1][1] != ' ')
        {
            return chessboard[0][2];    //判断左斜线是否相同
        }
        if (if_full(chessboard,row,col)) //判断是否平局,平局返回‘Q’
        {
            return 'Q';
        }


        return 'P';

    }

好了,今天就到这了。如有瑕疵,请多指教。

 

  • 14
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会背雨霖铃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值