三子棋程序

我们都玩过五子棋,只要有五个棋子连在一起就算赢。三子棋就是在五子棋的基础上简化一下,三个棋子连在一起就算赢。

一、文件编排

1.需要创建的文件

一个头文件(game.h)和两个源文件(game.c和function.c)

2.文件的作用

(1)game.h:负责放置函数的声明,头文件引用和标识符常量的定义。

(2)game.c:负责放置主程序的实现,包括进入、退出游戏的程序和游戏的整体实现的函数

(3)function.c:负责放置游戏整体实现函数的内部细节函数

二、实现游戏的进入和退出

1.整体逻辑

(1)首先我们需要打印选择界面,让玩家可以直到如何选择,此时就需要一个menu()函数。

(2)定义一个变量,允许玩家输入值,用switch语句输入1开始游戏,0退出游戏,输入其他数值就重新输入

(3)这个程序需要一个循环,不管玩家想玩还是不想玩,我们都应该先让他可以选择,此时我们使用do while循环

(4)判断条件为a,a输入值为0时,判断为假,跳出循环

(5)我们可以把需要使用的头文件的引用放在game.h这个文件中,在每个源文件中再引用这个头文件即可

2.代码

(1)game.c

#include"game.h"//头文件的引用放在game.h中
//游戏主程序的实现
void menu()
{
    printf("******************\n");
    printf("***** 1.play *****\n");
 
    printf("***** 0.exit *****\n");
    printf("******************\n");
}

   
int main()
{
    menu();//打印主界面
    int a = 0;
    do 
    {
        printf("请输入:");
        scanf("%d", &a);
        switch (a)
        {
        case 0:
            {
	        printf("退出游戏");//输入0退出
	        break;
	    }
	case 1:
	    {
	    printf("开始游戏\n");//输入1开始
	    game();//游戏的主程序此时还没有编写
	    break;
	    }
	default:
	    {
	    printf("请重新输入\n");//输入其他数字重新输入
	    break;
	    }
	}
	} while (a);
	return 0;
}

(2)game.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1//这句话在VS中使用scanf函数时需要,其他开发程序不需要


#include<stdio.h>

三、实现棋盘的初始化与打印

1、整体逻辑

(1)此时当玩家选择1时,我们需要进入game()的游戏主程序,我们先将游戏初始化。

(2)我们先创建一个3×3的字符数组board作为棋盘,但当我们想把这个游戏改为五子棋的时候,所有涉及到元素个数的代码全部需要修改,我们就在头文件中定义两个标识符常量ROW(行)和COL(列)为3,此时当我们想改动代码时就不需要去修改程序中涉及字符个数的每一个3。

(3)初始化需要两个函数,一个用于初始化数组的每一个元素为空格,另一个用于打印棋盘。

(4)注意在头文件中加入对应的函数声明。

2、函数讲解

game()函数中的函数放在function.c文件内

(1)初始化数组的每一个元素为空格

此处应用两个嵌套的循环即可

void initialboard(char board[ROW][COL], int row, int col)//初始化数组的每一个元素为空格
{
    int i = 0;
    for (i=0; i<row; i++)
    {
	    int j = 0;
	    for (j=0; j<col; j++)
	    {
	        board[i][j] = ' ';
	    }
    }
}

(2)打印棋盘

以下是我们需要打印的棋盘,同样,当我们修改数组元素的个数时,这个棋盘也需要发生改变,那么我们不妨去找找内部的某些规律。

   |   |   
---|---|---
   |   |   
---|---|---
   |   |   
共五行
我们可以把第一行进行拆分:
每一个元素就是:空格+元素+空格 和 |的交替,而最后一个|不需要打印
我们再把第二行进行拆分:
每一个元素就是:---- 和 |的交替,同样最后一个|不需要打印
所以这个程序可以通过选择和循环进行实现

写成程序后:

void printboard(char board[ROW][COL], int row, int col)//打印棋盘
{
    int i = 0;
    for (i=0; i<ROW ;i++)
    {
	
        int j = 0;
	    for (j = 0; j < col; j++)
	    {
	        printf(" %c ",board[i][j]);//打印三次 %c 
	        if (j<col-1)
	        {
	            printf("|");//打印两次|
	        }
	    }
	    printf("\n");
	    for (j = 0; j < col; j++)//进入循环三次
	    {
	        if (i<row-1)//最后一层不打印
	        {
                printf("---");
	            if (j < col - 1)
	            {
	                printf("|");//最后一个不打印
	            }
	        }
	    }
	    if (i<row-1)//美观,最后一个不换行
	    {
            printf("\n");
	    }
    }

}

3、代码

game.c中的重复代码不再重复,我们只需要展示game()函数的内容,注意在头文件中写函数的声明。

void game()
{
    char board[ROW][COL];//创建一个3×3的数组作为棋盘
    initialboard(board,ROW,COL);//初始化数组的每一个元素为空格
    printboard(board, ROW, COL);//打印棋盘
    //先写到初始化部分
}

四、玩家与电脑竞技的实现

1.整体逻辑

(1)需要两个函数,一个函数可以让玩家使用坐标下棋,另一个函数可以让电脑下棋。

(2)下棋实际上就是改变字符数组的元素,所以在改变数组的元素前需要保证这里储存的元素是个空格。

(3)电脑下棋实质就是让电脑自动生成坐标,判断后将空格变为不同于玩家的字符。

(4)生成坐标需要生成随机数的函数

2.函数讲解

(1)玩家下棋

玩家输入数字,比如:1 1

在改变数组的元素前需要保证这里储存的元素是个空格,然后改变内容

注意数组的下标是从零开始,行列都需要减1

void playermove(char board[ROW][COL],int row,int col)//玩家下棋
{
    printf("玩家下棋\n");
    while (1)
    {
        int i = 0;
	    int j = 0;
	    printf("请输入坐标:");
	    scanf("%d %d", &i, &j);
	    if (board[i-1][j-1] == ' ')//判断棋盘位是否被占用
	    {
	        board[i-1][j-1] = '*';//改变数组元素,相当于下棋
	        break;
	    }
	    else 
	    {
	        printf("请重新输入\n");
	    }
    }
}

(2)电脑下棋

电脑生成随机数,对3取余,可以得到两个随机的0、1、2,而在这里如果直接写3,当我们想实现5×5的五子棋时,这个函数又需要修改,所以我们直接对行数和列数取余即可。

在改变数组的元素前需要保证这里储存的元素是个空格,然后改变内容。

因为生成的数字正好满足数组的下标范围,所以这里生成的0、1等数字直接使用即可。

void computermove(char board[ROW][COL],int row,int col)//电脑下棋
{
    printf("电脑下棋\n");
    while (1)
    {
	    int i = rand() % row;//调用rand函数需要优先调用srand函数,srand函数在
	    int j = rand() % col;
	    if (board[i][j] == ' ')
    	{
	        board[i][j] = '#';
	        break;
	    }
    }
}

3.代码

void game()
{
    char board[ROW][COL];//创建一个3×3的数组作为棋盘
    initialboard(board,ROW,COL);//初始化数组的每一个元素为空格
    printboard(board, ROW, COL);//打印棋盘
    while (1)//死循环,此时我们还没有确定跳出条件
    {
        playermove(board,ROW,COL);//玩家下棋
        printboard(board, ROW, COL);//打印棋盘
		
        computermove(board,ROW,COL);//电脑下棋
	    printboard(board, ROW, COL);//打印棋盘

    }
}

五、对胜负平局的判断

1.整体逻辑

(1)需要一个函数,这个函数可以判断棋局当前的状态,根据不同的状态返回不同的字符。

例如:玩家胜利return *

电脑胜利return #

没人胜利同时还可以继续游戏return 'c'

所有的位置都被占满了,平局return 'q'。

(2)电脑和玩家每下一步棋,这个函数都需要运行一次。

(3)返回的不是代表游戏继续的字符就需要跳出循环,这个判断在game函数的循环中作为判断依据

(4)跳出下棋的循环后我们就需要判断返回的字符到底是哪一个,分别代表玩家胜利,电脑胜利和平局

2.函数讲解

判断胜负

在正方形的棋盘中,要想获胜就需要让自己的棋子连成一行、一列或者一斜对角线。我们需要逐个判断每一种获胜方法。

判断行,定义对应的count变量对棋子进行计数,若有一个变量等于行数代表有人胜利,返回对应的棋子。(其实我们可以直接把每一个元素进行比较,并且它们还需要满足不为空格)

判断列,判断对角线也是同样的道理

char judge(char board[ROW][COL], int row, int col)
{
    int i = 0;
    //判断行
    for (i=0; i<row; i++)
    {
        int j = 0;
	int count1 = 0;
	int count2 = 0;
	for (j = 0; j < col; j++)
	{
	    if (board[i][j] == '*')
	    {
	        count1++;
	    }
	    if (board[i][j] == '#')
	    {
	        count2++;
	    }
	    if (count1 == row)
		    return '*';
	    if (count2 == row)
		    return '#';
	}
    }
    
     
    //判断列
    for (i = 0; i < col; i++)
    {
        int j = 0;
	int count1 = 0;
	int count2 = 0;
	for (j = 0; j < row; j++)
	{
	    if (board[j][i] == '*')
	    {
	        count1++;
	    }
	    if (board[j][i] == '#')
	    {
	        count2++;
	    }
	    if (count1 == col)
	    	return '*';//玩家赢
	    if (count2 == col)
	        return '#';//电脑赢
	}
    }
    
     
    //判断对角线
    int count1 = 0;
    int count2 = 0;
    for (i = 0; i < row; i++)
    {		
        if (board[i][i] == '*')
	{
	    count1++;
	}
	if (board[i][i] == '#')
	{
	    count2++;
	}
	if (count1 == col)
	        return '*';//玩家赢
		if (count2 == col)
	        return '#';//电脑赢
    }
    int count3 = 0;
    int count4 = 0;
    for (i = 0; i < row; i++)
    {
        if (board[row-1-i][i] == '*')
	{
	    count3++;
	}
	if (board[row-1-i][i] == '#')
	{
	    count4++;
	}
	if (count3 == col)
	    return '*';//玩家赢
	if (count4 == col)
	    return '#';//电脑赢
    }
    
     
    //判断是否平局
    int count = 0;
    for (i = 0; i < row; i++)
    {
        int j = 0;
	
    for (j = 0; j < col; j++)
	{
	    if (board[i][j] == ' ')
	    {
	        count++;
	    }
	}
    }
    if (count == 0)
    {
        return 'q';//平局
    }
	
	
	return 'c';//都不满足,继续游戏
}

3.代码

game.c

void game()
{
    char board[ROW][COL];//创建一个3×3的数组作为棋盘
    initialboard(board,ROW,COL);//初始化数组的每一个元素为空格
    printboard(board, ROW, COL);//打印棋盘
    char ret = 0;
    while (1)
    {
        playermove(board,ROW,COL);//玩家下棋
	printboard(board, ROW, COL);//打印棋盘
	ret = judge(board, ROW, COL);//判断胜负
	if (ret != 'c')
	    break;
	computermove(board,ROW,COL);//电脑下棋
	printboard(board, ROW, COL);//打印棋盘
	ret = judge(board, ROW, COL);//判断胜负
	if (ret != 'c')
	    break;
    }
    if (ret == 'q')
    {
        printf("平局\n");
    }
    else if (ret == '*')
    {
	printf("玩家胜利\n");
    }
    else if (ret == '#')
    {
        printf("电脑胜利\n");
    }
}

六、成品(白嫖的直接看这里)

game.h

#pragma once

#define _CRT_SECURE_NO_WARNINGS 1//这个只在VS上使用
#define ROW 3
#define COL 3

 //函数声明

void initialboard(char board[ROW][COL], int row, int col);//初始化数组的每一个元素为空格
void printboard(char board[ROW][COL], int row, int col);//打印棋盘
void playermove(char board[ROW][COL], int row, int col);//玩家下棋
void computermove(char board[ROW][COL], int row, int col);//电脑下棋
char judge(char board[ROW][COL], int row, int col);//判断胜负

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

game.c

#include"game.h"
//游戏主程序的实现
void menu()
{
    printf("******************\n");
    printf("***** 1.play *****\n");
    printf("***** 0.exit *****\n");
    printf("******************\n");
}



void game()
{
    char board[ROW][COL];//创建一个3×3的数组作为棋盘
    initialboard(board,ROW,COL);//初始化数组的每一个元素为空格
    printboard(board, ROW, COL);//打印棋盘
    char ret = 0;
    while (1)
    {
        playermove(board,ROW,COL);//玩家下棋
	printboard(board, ROW, COL);//打印棋盘
	ret = judge(board, ROW, COL);//判断胜负
	if (ret != 'c')
	    break;
	computermove(board,ROW,COL);//电脑下棋
	printboard(board, ROW, COL);//打印棋盘
	ret = judge(board, ROW, COL);//判断胜负
	if (ret != 'c')
	    break;
    }
    if (ret == 'q')
    {
        printf("平局\n");
    }
    else if (ret == '*')
    {
        printf("玩家胜利\n");
    }
    else if (ret == '#')
    {
	printf("电脑胜利\n");
    }
}

   

int main()
{
    srand((unsigned int)time(NULL));
    int a = 0;
    do 
    {
	menu();//打印主界面
	printf("请输入:");
	scanf("%d", &a);
	switch (a)
	{
	case 0:
	    {
	    printf("退出游戏");//输入0退出
	    break;
	    }
	case 1:
	    {
		printf("开始游戏\n");//输入1开始
		game();//游戏的主程序
		break;
	    }
	default:
	    {
		printf("请重新输入\n");//输入其他数字重新输入
		break;
	    }
	}
    } while (a);
    return 0;
}

function.c

#include"game.h"

 

void initialboard(char board[ROW][COL], int row, int col)//初始化数组的每一个元素为空格
{
    int i = 0;
    for (i=0; i<row; i++)
    {
	int j = 0;
	for (j=0; j<col; j++)
	{
	    board[i][j] = ' ';
	}
    }
}


void printboard(char board[ROW][COL], int row, int col)//打印棋盘
{
    int i = 0;
    for (i=0; i<ROW ;i++)
    {
	int j = 0;
	for (j = 0; j < col; j++)
	{
	    printf(" %c ",board[i][j]);
	    if (j<col-1)
	    {
	        printf("|");
	    }
	}
	printf("\n");
	for (j = 0; j < col; j++)
	{
	    if (i<row-1)
	    {
                printf("---");
	        if (j < col - 1)
	        {
		    printf("|");
	        }
	    }
	}
	if (i<row-1)
	{
            printf("\n");
	}
    }
}
//   |   |  
//---|---|---
//   |   |   
//---|---|---
//   |   |   
//我们可以把第一行进行拆分:
//每一个元素就是:空格+元素+空格 和 |的交替,而最后一个|不需要打印
//我们再把第二行进行拆分:
//每一个元素就是:---- 和 |的交替,同样最后一个|不需要打印
//所以这个程序可以通过选择和循环进行实现

   

void playermove(char board[ROW][COL],int row,int col)//玩家下棋
{
    printf("玩家下棋\n");
    while (1)
    {
	int i = 0;
	int j = 0;
	printf("请输入坐标:");
	scanf("%d %d", &i, &j);
	if (board[i-1][j-1] == ' ')
	{
	    board[i-1][j-1] = '*';
	    break;
	}
	else 
	{
	    printf("请重新输入\n");
	}
    }
}

 

void computermove(char board[ROW][COL],int row,int col)//电脑下棋
{
    printf("电脑下棋\n");
    while (1)
    {
	int i = rand() % ROW;
	int j = rand() % COL;
	if (board[i][j] == ' ')
	{
	    board[i][j] = '#';
	    break;
	}
    }
}

 

//判断胜负
//玩家胜利return *
//电脑胜利return #
//没人胜利同时还可以继续游戏return 'c'
//所有的位置都被占满了,return 'q'
char judge(char board[ROW][COL], int row, int col)
{
    int i = 0;
    //判断行
    for (i=0; i<row; i++)
    {
        int j = 0;
	int count1 = 0;
	int count2 = 0;
	for (j = 0; j < col; j++)
	{
	    if (board[i][j] == '*')
	    {
	        count1++;
	    }
	    if (board[i][j] == '#')
	    {
	        count2++;
	    }
	    if (count1 == row)
		return '*';
	    if (count2 == row)
		return '#';
	}
    }
    
     
    //判断列
    for (i = 0; i < col; i++)
    {
        int j = 0;
	int count1 = 0;
	int count2 = 0;
	for (j = 0; j < row; j++)
	{
	    if (board[j][i] == '*')
	    {
	        count1++;
	    }
	    if (board[j][i] == '#')
	    {
	        count2++;
	    }
	    if (count1 == col)
		return '*';//玩家赢
	    if (count2 == col)
	        return '#';//电脑赢
	}
    }
    
     
    //判断对角线
    int count1 = 0;
    int count2 = 0;
    for (i = 0; i < row; i++)
    {		
        if (board[i][i] == '*')
	{
	    count1++;
	}
	if (board[i][i] == '#')
	{
	    count2++;
	}
	if (count1 == col)
	    return '*';//玩家赢
		if (count2 == col)
	    return '#';//电脑赢
    }
    int count3 = 0;
    int count4 = 0;
    for (i = 0; i < row; i++)
    {
        if (board[row-1-i][i] == '*')
	{
	    count3++;
	}
	if (board[row-1-i][i] == '#')
	{
	    count4++;
	}
	if (count3 == col)
	    return '*';//玩家赢
	if (count4 == col)
	    return '#';//电脑赢
    }
    
     
    //判断是否平局
    int count = 0;
    for (i = 0; i < row; i++)
    {
        int j = 0;
	
for (j = 0; j < col; j++)
	{
	    if (board[i][j] == ' ')
	    {
	        count++;
	    }
	}
    }
    if (count == 0)
    {
        return 'q';//平局
    }
	
	
    return 'c';//都不满足,继续游戏
}

这个程序改变ROW和COL的值就可以扩大棋盘,并且以对应行,列和对角线的相连判断获胜。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值