24点游戏-去除重复结果

game.c

/*
 * game.c
 *
 *  Created on: 2011-9-27
 *      Author: brunie
 */

#include "game.h"
#include "stack.h"

Node* standardize_tree(Node* root);
int save_unique(Game *game, Node *root);
void get_expression(Node *root, char *exp);
Node *copy_tree(Node *root);
void destroy_tree(Node *root);

int operate(Node *left, Node *right, Node *result, int type)
{
    switch (type)
    {
        case ADD:
            result->res = left->res + right->res;
            result->op = '+';
            result->left = left;
            result->right = right;
            break;

        case SUB:
            result->res = left->res - right->res;
            result->op = '-';
            result->left = left;
            result->right = right;
            break;

        case MUL:
            result->res = left->res * right->res;
            result->op = '*';
            result->left = left;
            result->right = right;
            break;

        case DIV:
            if (right->res != 0)
            {
                result->res = left->res / right->res;
                result->op = '/';
                result->left = left;
                result->right = right;
            }
            break;

        case RSUB:
            result->res = right->res - left->res;
            result->op = '-';
            result->left = right;
            result->right = left;
            break;

        case RDIV:
            if (left->res != 0)
            {
                result->res = right->res / left->res;
                result->op = '/';
                result->left = right;
                result->right = left;
            }
            break;
    }
    return 1;
}

int calculate(Node **node_list, int len, Game *game)
{
    int i, j, k, tmp, type;
    if (len == 1)
    {
        if (fabs(node_list[0]->res - FINAL_RESULT) < PRECISION)
        {
            save_unique(game, node_list[0]);
            game->success = OK;
        }
    }
    else
    {
        Node **next = (Node **) malloc((len - 1) * sizeof(pNode));
        pNode tmp_result = (pNode) malloc(sizeof(Node));
        next[0] = tmp_result;
        for (i = 0; i < len; i++)
        {
            for (j = i + 1; j < len; j++)
            {

                tmp = 1;
                for (k = 0; k < len; k++)
                {
                    if (k != i && k != j)
                    {
                        next[tmp++] = node_list[k];
                    }
                }

                for (type = 0; type < OPERATOR_TYPES; type++)
                {
                    operate(node_list[i], node_list[j], tmp_result, type);

                    calculate(next, len - 1, game);
                }
            }
        }// for i

        free(next);
        free(tmp_result);

    }//else
    return 1;
}

void Game_execute(Game *game)
{
    calculate(game->node_list, N_FIGURES, game);
}

int priority(char operator)
{
    if (operator == 0)
        return 3;
    else if (operator == '+' || operator == '-')
        return 1;
    else
        return 2;
}

Node* copy_tree(Node *root)
{
    if (0 == root)
        return 0;

    Node *new_root = (Node *)malloc(sizeof(Node));
    *new_root = *root;

    new_root->left = copy_tree(root->left);
    new_root->right = copy_tree(root->right);

    return new_root;
}

void destroy_tree(Node *root)
{
    if (root->left)
        destroy_tree(root->left);
    if (root->right)
        destroy_tree(root->right);

    free(root);

}

void sort_node(pNode *pnodes, int len)
{
    int i,j;
    int flag = 1;
    for (i = 0; i < len - 1 && flag; i++)
    {
        flag = 0;
        for (j = 0; j < len - i - 1; j++)
        {
            if (pnodes[j]->res > pnodes[j + 1]->res)
            {
                pNode tmp = pnodes[j];
                pnodes[j] = pnodes[j + 1];
                pnodes[j + 1] = tmp;
                flag = 1;
            }
        }
    }

    /*for (i = 0; i < len; i++)
        printf("%f ", (*pnodes[i])->res);
    printf("\n");*/
}

Node* create_tree(pNode *left_nodes, int left_len,
        pNode *right_nodes, int right_len, char op)
{
    sort_node(left_nodes, left_len);
    sort_node(right_nodes, right_len);
    pNode left_result, right_result;
    int type;
    int i;
    if (op == '+')
        type = ADD;
    else
        type = MUL;
    if (left_len >= 2)
    {
        for (i = 0; i < left_len - 1; i++)
        {
            left_result = (pNode) malloc(sizeof(Node));
            operate(left_nodes[i], left_nodes[i + 1], left_result, type);
            left_nodes[i + 1] = left_result;
        }
    }
    else
    {
        left_result = left_nodes[0];
    }

    if (right_len >= 1)
    {
        for (i = 0; i < right_len; i++)
        {
            right_result = (pNode) malloc(sizeof(Node));
            operate(left_result, right_nodes[i], right_result, type + 1);
            left_result = right_result;
        }
    }

    return left_result;
}

Node* standardize_tree(Node* root)
{
    Node   *tmp, *mid_root;
    istack *open = (istack*)malloc(sizeof(istack));
    pNode left_nodes[N_FIGURES];
    pNode right_nodes[N_FIGURES];
    int left_len = 0, right_len = 0;
    char op_a, op_b, op;

    init_stack(open);
    tmp = root;
    op = tmp->op;
    if (op == '+' || op == '-')
    {
        op = op_a = '+';
        op_b = '-';
    }
    else
    {
        op = op_a = '*';
        op_b = '/';
    }

    do
    {
        if (tmp->op == op_a)
        {
            push(open, tmp);
            tmp = tmp->left;
        }
        else if (tmp->op == op_b)
        {
            push(open, tmp);

            mid_root = tmp->right;
            if (tmp->right->op)
                mid_root = standardize_tree(tmp->right);
            right_nodes[right_len++] = mid_root;
            tmp->right = 0;

            tmp = tmp->left;
        }
        else
        {
            mid_root = tmp;
            if (tmp->op)
                mid_root = standardize_tree(tmp);
            left_nodes[left_len++] = mid_root;

            if (!stack_empty(open))
            {
                pop(open, &tmp);
                while (!tmp->right && !stack_empty(open))
                {
                    free(tmp);
                    pop(open, &tmp);
                }

                mid_root = tmp;
                tmp = tmp->right;
                if (mid_root->op)
                    free(mid_root);
            }
            else
                tmp = 0;
        }
    } while (tmp || !stack_empty(open));

    free(open);

    mid_root = create_tree(left_nodes, left_len, right_nodes, right_len, op);

    return mid_root;
}


int save_unique(Game *game, Node* root)
{
    int i;
    char *exp = (char*) malloc(EXPRESSION_LEN);
    exp[0] = '\0';
    Node *tmp_root = copy_tree(root);
    tmp_root = standardize_tree(tmp_root);
    get_expression(tmp_root, exp);

    //printf("%s\n", exp);

    destroy_tree(tmp_root);
    for (i = 0; i < game->n_solutions; i++)
    {
        if (strcmp(exp, game->unique_expressions[i]) == 0)
        {
            break;
        }
    }

    if (i == game->n_solutions)
    {
        if (game->n_solutions == MAX_N_SOLUTIONS)
        {
            game->unique_expressions = (char **) realloc(
                    game->unique_expressions,
                    (game->n_solutions + MAX_N_SOLUTIONS) * sizeof(char*));
            if (!game->unique_expressions)
                exit(OVERFLOW);
        }
        game->unique_expressions[game->n_solutions++] = exp;
        return TRUE;
    }
    return FALSE;
}


void get_expression(Node *root, char *exp)
{
    char left_op, right_op, op;

    if (root->left == 0 && root->right == 0)
    {
        sprintf(exp + strlen(exp),"%d", (int)(root->res));
    }
    else
    {
        left_op = root->left->op;
        right_op = root->right->op;
        op = root->op;
        if (priority(op) > priority(left_op))
        {
            sprintf(exp + strlen(exp),"(");
            get_expression(root->left, exp);
            sprintf(exp + strlen(exp),")");
        }
        else
            get_expression(root->left, exp);

        sprintf(exp + strlen(exp), " %c ", op);

        if (priority(op) > priority(right_op)
            || (op == '-' && right_op == '-')
            || (op == '-' && right_op == '+')
            || (op == '/' && right_op == '*')
            || (op == '/' && right_op == '/'))
        {
            sprintf(exp + strlen(exp), "(");
            get_expression(root->right, exp);
            sprintf(exp + strlen(exp), ")");
        }
        else
            get_expression(root->right, exp);
    }
}

void print_results(Game *game)
{
    printf("\nTotal %d unique results:\n", game->n_solutions);
    int i;
    for (i = 0; i < game->n_solutions; i++)
    {
        printf("%s = %d\n", game->unique_expressions[i], FINAL_RESULT);
    }
}

void init_list(Game *game)
{
    int i;
    game->success = 0;
    game->n_solutions = 0;
    for (i = 0; i < N_FIGURES; i++)
    {
        game->node_list[i]->res = game->figures[i];
    }
}

int init_data(Game *game)
{
    int i;
    game->figures = (int *)malloc(N_FIGURES * sizeof (int));
    game->node_list = (pNode *)malloc(N_FIGURES * sizeof (pNode));
    game->unique_expressions = (char **)malloc(MAX_N_SOLUTIONS * sizeof (char *));

    if (!(game->figures && game->node_list && game->unique_expressions))
        exit(OVERFLOW);

    for (i = 0; i < N_FIGURES; i++)
    {
        game->node_list[i] = (pNode)malloc(sizeof(Node));
        if (!game->node_list[i])
            exit(OVERFLOW);
        game->node_list[i]->left = 0;
        game->node_list[i]->right = 0;
        game->node_list[i]->op = 0;
    }

    return TRUE;
}

void destory_data(Game *game)
{
    int i;
    if (game->figures)
    {
        free(game->figures);
        game->figures = 0;
    }
    if (game->node_list)
    {
        for (i = 0; i < N_FIGURES; i++)
        {
            free(game->node_list[i]);
        }
        free(game->node_list);
        game->node_list = 0;
    }
    if (game->unique_expressions)
    {
        for (i = 0; i < game->n_solutions; i++)
        {
            free(game->unique_expressions[i]);
        }
        free(game->unique_expressions);
        game->unique_expressions = 0;
    }

}



game.h

/*
 * game.h
 *
 *  Created on: 2011-9-27
 *      Author: brunie
 */

#ifndef GAME_H_
#define GAME_H_

#define MAX_INPUT 		13
#define MIN_INPUT 		1
#define N_FIGURES		4
#define OPERATOR_TYPES	6
#define FINAL_RESULT	24
#define EXPRESSION_LEN 	30
#define MAX_N_SOLUTIONS 100
#define PRECISION		(1E-6)

#define TRUE			1
#define FALSE			0
#define OK				1
#define OVERFLOW		(-2)

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

typedef struct Node
{
	double res;
	struct Node *left;
	struct Node *right;
	char op;
}Node, *pNode;

enum Operators {ADD, SUB, MUL, DIV, RSUB, RDIV};

typedef struct Game
{
	int *figures;
	pNode *node_list;
	int success;
	int n_solutions;
	char **unique_expressions;
}Game, *pGame;

void Game_execute(Game *game);

void print_results(Game *game);

void init_list(Game *game);

int init_data(Game *game);

void destory_data(Game *game);

#endif /* GAME_H_ */

main.c

/*
 * main.c
 *
 *  Created on: 2011-9-27
 *      Author: brunie
 */

#include "twenty_four.h"

int main()
{
	setbuf(stdout,0);
	int status;
	status = play_game();

	if (status)
		printf("Successful!\n");
	else
		printf("Not exist!\n");

	return 0;
}

stack.c

/*
 * stack.c
 *
 *  Created on: 2011-10-5
 *      Author: brunie
 */
#include "stack.h"

int init_stack(istack *stack)
{
	stack->base = (pNode *)malloc(STACK_INIT_SIZE * sizeof(pNode));
	if (!stack->base)
		exit (-1);
	stack->top = stack->base;
	stack->stack_size = STACK_INIT_SIZE;
	return 1;
}

void destory_stack(istack *stack)
{
	if(!stack->base)
		free(stack->base);
	stack->base = 0;
}

int stack_empty(istack *stack)
{
	if (stack->top == stack->base)
		return TRUE;
	else
		return FALSE;
}

int stack_length(istack *stack)
{
	return stack->top - stack->base;
}

int get_top(istack *stack, pNode *pnode)
{
	if (stack->top == stack->base)
		return 0;
	*pnode = *(stack->top - 1);
	return 1;
}

int push(istack *stack, pNode pnode)
{
	if (stack->top - stack->base >= stack->stack_size)
	{
		stack->base = (pNode *) realloc(stack->base,
				(stack->stack_size + STACK_INCREMENT) * sizeof(pNode));
		if (!stack->base)
			exit(-1);
		stack->top = stack->base + stack->stack_size;
		stack->stack_size += STACK_INCREMENT;
	}
	*stack->top++ = pnode;
	return 1;
}

int pop(istack *stack, pNode *pnode)
{
	if (stack->top == stack->base)
		return 0;
	*pnode = * --stack->top;
	return 1;
}

stack.h

/*
 * stack.h
 *
 *  Created on: 2011-10-5
 *      Author: brunie
 */

#ifndef STACK_H_
#define STACK_H_

#include "game.h"

#define	STACK_INIT_SIZE	50
#define	STACK_INCREMENT	10

typedef struct
{
	pNode	*base;
	pNode	*top;
	int		stack_size;
}istack;

int init_stack(istack *stack);

void destory_stack(istack *stack);

int stack_empty(istack *stack);

int stack_length(istack *stack);

int get_top(istack *stack, pNode *pnode);

int pop(istack *stack, pNode *pnode);

int push(istack *stack, pNode pnode);

#endif /* STACK_H_ */

twenty_four.c

/*
 * twenty_four.c
 *
 *  Created on: 2011-10-5
 *      Author: brunie
 */

#include "twenty_four.h"

void input(Game *game)
{
	int digit;
	int c;
	int i;

	while(1)
	{
		printf("Please input %d figures, each figure in the range of [%d,%d]:\n",N_FIGURES, MIN_INPUT, MAX_INPUT);
		digit = 0;
		i = 0;

		while ((c = getchar()) == ' ');

		do
		{
			if (c <= '9' && c >= '0')
				digit = digit * 10 + c - '0';
			else if (c == ' ')
			{
				if (digit > MAX_INPUT || digit < MIN_INPUT)
					break;
				game->figures[i++] = digit;
				//printf("%d ",digit);

				if (i == N_FIGURES)
					break;

				while((c = getchar()) == ' ');
				if(c > '9' || c < '0')
					break;
				digit = c - '0';
			}
			else
			{
				if (c == '\n')
				{
					game->figures[i++] = digit;
					//printf("%d ",digit);
				}
				break;
			}

		}while ((c = getchar()) != EOF);

		if (c != '\n')
			while ((c = getchar()) != '\n');

		if (i == N_FIGURES)
			break;

		printf("Illegal input!\n");
	}

}


int play_game()
{

	int c;
	int flag;

	Game game;

	init_data(&game);

	do
	{
		input(&game);
		init_list(&game);
		Game_execute(&game);
		print_results(&game);

		printf("Do you want to play again(y/n):");
		flag = getchar();
		while ((c = getchar()) != '\n' && c != EOF)
			;
	} while (flag == 'y' || flag == 'Y');

	destory_data(&game);

	return game.success;
}

tweny_four.h

/*
 * twenty_four.h
 *
 *  Created on: 2011-10-5
 *      Author: brunie
 */

#ifndef TWENTY_FOUR_H_
#define TWENTY_FOUR_H_

#include "game.h"

void input(Game *game);

int play_game();

#endif /* TWENTY_FOUR_H_ */



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值