CSC3150 Assignment2 代码参考

assignmnet2主要是多线程编写一个青蛙过河的小游戏
语言:C++
环境:
在这里插入图片描述
就目前所见做法主要分为两类:将木板移动和青蛙移动分为两部分。第二种是将河的每一条都进行划分,这里我主要采取第二种。(感觉查重率会很低,而且这个方法有自己的问题,我也没搞懂)

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <curses.h>
#include <termios.h>
#include <fcntl.h>

#define ROW 10
#define COLUMN 50

pthread_mutex_t mutex;
pthread_mutex_t mutex2;


struct Node{
	int x , y; 
	Node( int _x , int _y ) : x( _x ) , y( _y ) {}; 
	Node(){} ; 
} frog ; 


char map[ROW+10][COLUMN] ;
int state = 0; // 0: the game is in progress, 1: win, 2: lose, 3: quit

// Determine a keyboard is hit or not. If yes, return 1. If not, return 0. 
int kbhit(void){
	struct termios oldt, newt;
	int ch;
	int oldf;

	tcgetattr(STDIN_FILENO, &oldt);

	newt = oldt;
	newt.c_lflag &= ~(ICANON | ECHO);

	tcsetattr(STDIN_FILENO, TCSANOW, &newt);
	oldf = fcntl(STDIN_FILENO, F_GETFL, 0);

	fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

	ch = getchar();

	tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
	fcntl(STDIN_FILENO, F_SETFL, oldf);

	if(ch != EOF)
	{
		ungetc(ch, stdin);
		return 1;
	}
	return 0;
}

void *frog_move( void *threadid){

        pthread_mutex_lock(&mutex2);
            
        char optation = getchar();
        if (frog.x == ROW ){
            map[frog.x][frog.y] = '|';
        }
		else if (frog.x != ROW){
			map[frog.x][frog.y] = '=';
		}
        if (optation == 'w' || optation == 'W'){
            frog.x -= 1;
        }
        else if (optation == 's' || optation == 'S'){
            frog.x += 1;
        }
        else if (optation == 'a' || optation == 'A'){
            frog.y -= 1;
        }
        else if (optation == 'd' || optation == 'D'){
            frog.y += 1;
        }
        else if (optation == 'q' || optation == 'Q'){
            state = 3;
        }
        pthread_mutex_unlock(&mutex2);
        pthread_exit(NULL);
}

int water_speed(int x){
            if (x == 1 || x == 3 || x == 5 || x == 7 || x == 9){      //青蛙在木板上的固有流速
            return -1;
            }
            else if (x == 2 || x == 4 || x == 6 || x == 8){ 
            return 1;
}
}

void *logs_move( void *t ){
    long riv;
    riv = (long) t+1;
    
	/*  Move the logs  */
    int loghead = rand()% (COLUMN-10)+10;
    int length = 15;

    pthread_mutex_lock(&mutex);

    while (state == 0){
        int condition = 0; 
            usleep(70000);    

        /*  Check keyboard hits, to change frog's position or quit the game. */
        if (kbhit()){

        pthread_t threads_frog;
        int rc;
        rc = pthread_create(&threads_frog,NULL,frog_move, NULL);
        if (rc){
            printf("ERROR: return code from pthread_create() is %d", rc);
            exit(1);
        }           
        }
        
		for (int i = 1;i<=50;i++){                //每次刷新都是先铺好空格,然后再将空格改为 =
			map[riv][(i+COLUMN)%(COLUMN-1)]=' ';
		}

        if (frog.x==riv){
            frog.y += water_speed(riv);
        }
        
        if (riv == 1 || riv == 3 || riv == 5 || riv == 7 || riv == 9){ // left
            for (int j=15+loghead;j>=loghead;j--){
                if (frog.x==riv && (frog.y+1)==(j+50)%49){    
                    condition=1;
                }
                map[riv][(j+50)%(49)]='=';
            }
            if (frog.y+1==(loghead+50)%(49)){
                condition=0;
            }
            loghead=(loghead+49)%(50);
        }
        else if (riv == 2 || riv == 4 || riv == 6 || riv == 8){ // right
            for (int j=loghead;j<=length+loghead;j++){
                if (frog.x==riv && (frog.y-1)==j%(49)){
                    condition=1;
                }
                map[riv][j%(49)]='=';
            }
            if (frog.y==(length+loghead+50)%49){
                condition=0;
            }
            loghead=(loghead+1)%(49);
        }
        map[frog.x][frog.y] = '0';

        /*  Check game's status  */
        if (frog.x > ROW || frog.y < 1 || frog.y > 48 || (!condition && frog.x==riv)){
            state = 2;
        }
        if (frog.x == 0){
            state = 1;
        }
        /*  Print the map on the screen  */
        if (riv == 1){
            printf("\033[H\033[2J");
            for(int i = 0; i <= ROW; i++){
                puts(map[i]);
            }

            if (state==1){
                pthread_exit(NULL);
            }
            else if (state==2){
                pthread_exit(NULL);
            }
            else if (state==3){
                pthread_exit(NULL);
            }
        }
        pthread_mutex_unlock(&mutex);
    }

    pthread_exit(NULL);
}

int main( int argc, char *argv[] ){

	// Initialize the river map and frog's starting position
	memset( map , 0, sizeof( map ) ) ;
	int i , j ; 
	for( i = 1; i < ROW; ++i ){	
		for( j = 0; j < COLUMN - 1; ++j )	
			map[i][j] = ' ' ; 
	}
    for( j = 0; j < COLUMN - 1; ++j ){
        map[ROW][j] = map[0][j] = '|' ; 
    }
	for( j = 0; j < COLUMN - 1; ++j )	
		map[0][j] = map[0][j] = '|' ;

	frog = Node( ROW, (COLUMN-1) / 2 ) ;
	map[frog.x][frog.y] = '0' ;

	//Print the map into screen
    printf("\033[H\033[2J");
	for( i = 0; i <= ROW; ++i)	
		puts( map[i] );

	/*  Create pthreads for wood move and frog control.  */

    pthread_t threads[ROW-1];
    int rc;
    pthread_mutex_init(&mutex, NULL);
    pthread_mutex_init(&mutex2, NULL);

    for (long k=0;k<ROW-1;k++){
        rc = pthread_create(&threads[k],NULL,logs_move, (void*)k);
        if (rc){
            printf("ERROR: return code from pthread_create() is %d", rc);
            exit(1);
        }
    }
    pthread_join(threads[0],NULL);

    /* Display the output for user: win, lose or quit. */
    if (state==1){
        printf("\033[H\033[2JYou win the game!!\n");
        }
        else if (state==2){
            printf("\033[H\033[2JYou lose the game!!\n");
        }
        else if (state==3){
            printf("\033[H\033[2JYou exit the game.\n");
        }

    pthread_mutex_destroy(&mutex);
    pthread_mutex_destroy(&mutex2);
    pthread_exit(NULL);
	return 0;

}

借鉴了部分前人的想法,但是在结构上面优化了不少。(主要不变的部分是青蛙在木板上的判定之类的)

写的时候遇到的主要问题是如果有多线程输出的话输出结果会一直闪,所以在这里用 if (riv == 1)来只输出一次即可。

还有一个问题是输出的时候有时没法结束程序,有的时候可以,有的时候也会报错,具体原因尚未深究。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值