Task: Greed


C++: #include <windows.h>
#include <iostream>
#include <ctime>

const int WID = 79, HEI = 22;
const float NCOUNT = ( float )( WID * HEI );

class coord : public COORD {
public:
    coord( short x = 0, short y = 0 ) { set( x, y ); }
    void set( short x, short y ) { X = x; Y = y; }
};
class winConsole {
public:
    static winConsole* getInstamnce() { if( 0 == inst ) { inst = new winConsole(); } return inst; }
    void showCursor( bool s ) { CONSOLE_CURSOR_INFO ci = { 1, s }; SetConsoleCursorInfo( conOut, &ci ); }
    void setColor( WORD clr ) { SetConsoleTextAttribute( conOut, clr ); }
    void setCursor( coord p ) { SetConsoleCursorPosition( conOut, p ); }
    void flush() { FlushConsoleInputBuffer( conIn ); }
    void kill() { delete inst; }
private:
    winConsole() { conOut = GetStdHandle( STD_OUTPUT_HANDLE ); 
                   conIn  = GetStdHandle( STD_INPUT_HANDLE ); showCursor( false ); }
    static winConsole* inst;
    HANDLE conOut, conIn;
};
class greed {
public:
    greed() { console = winConsole::getInstamnce(); }
    ~greed() { console->kill(); }
    void play() {
        char g; do {
            console->showCursor( false ); createBoard();
            do { displayBoard(); getInput(); } while( existsMoves() );
            displayBoard(); console->setCursor( coord( 0, 24 ) ); console->setColor( 0x07 );
            console->setCursor( coord( 19,  8 ) ); std::cout << "+----------------------------------------+";
            console->setCursor( coord( 19,  9 ) ); std::cout << "|               GAME OVER                |";
            console->setCursor( coord( 19, 10 ) ); std::cout << "|            PLAY AGAIN(Y/N)?            |";
            console->setCursor( coord( 19, 11 ) ); std::cout << "+----------------------------------------+";
            console->setCursor( coord( 48, 10 ) ); console->showCursor( true ); console->flush(); std::cin >> g;
        } while( g == 'Y' || g == 'y' );
    }
private:
    void createBoard() {
        for( int y = 0; y < HEI; y++ ) {
            for( int x = 0; x < WID; x++ ) {
                brd[x + WID * y] = rand() % 9 + 1;
            }
        }
        cursor.set( rand() % WID, rand() % HEI );
        brd[cursor.X + WID * cursor.Y] = 0; score = 0;
        printScore();
    }
    void displayBoard() {
        console->setCursor( coord() ); int i;
		for( int y = 0; y < HEI; y++ ) {
            for( int x = 0; x < WID; x++ ) {
                i = brd[x + WID * y]; console->setColor( 6 + i );
                if( !i ) std::cout << " "; else std::cout << i;
            }
            std::cout << "\n";
        }
        console->setColor( 15 ); console->setCursor( cursor ); std::cout << "@";
    }
    void getInput() { 
        while( 1 ) {
            if( ( GetAsyncKeyState( 'Q' ) & 0x8000 ) && cursor.X > 0 && cursor.Y > 0 ) { execute( -1, -1 ); break; }
            if( ( GetAsyncKeyState( 'W' ) & 0x8000 ) &&  cursor.Y > 0 ) { execute( 0, -1 ); break; }
            if( ( GetAsyncKeyState( 'E' ) & 0x8000 ) && cursor.X < WID - 1 && cursor.Y > 0 ) { execute( 1, -1 ); break; }
            if( ( GetAsyncKeyState( 'A' ) & 0x8000 ) && cursor.X > 0 ) { execute( -1, 0 ); break; }
            if( ( GetAsyncKeyState( 'D' ) & 0x8000 ) && cursor.X < WID - 1 ) { execute( 1, 0 ); break; }
            if( ( GetAsyncKeyState( 'Y' ) & 0x8000 ) && cursor.X > 0 && cursor.Y < HEI - 1 ) { execute( -1, 1 ); break; }
            if( ( GetAsyncKeyState( 'X' ) & 0x8000 ) && cursor.Y < HEI - 1 ) { execute( 0, 1 ); break; }
            if( ( GetAsyncKeyState( 'C' ) & 0x8000 ) && cursor.X < WID - 1 && cursor.Y < HEI - 1 ) { execute( 1, 1 ); break; }
        }
        console->flush(); printScore();
    }
    void printScore() {
        console->setCursor( coord( 0, 24 ) ); console->setColor( 0x2a );
        std::cout << "      SCORE: " << score << " : " << score * 100.f / NCOUNT << "%      ";
    }
    void execute( int x, int y ) {
        int i = brd[cursor.X + x + WID * ( cursor.Y + y )];
        if( countSteps( i, x, y ) ) {
            score += i;
            while( i ) {
                --i; cursor.X += x; cursor.Y += y;
                brd[cursor.X + WID * cursor.Y] = 0;
            }
        }
    }
    bool countSteps( int i, int x, int y ) {
        coord t( cursor.X, cursor.Y );
        while( i ) {
            --i; t.X += x; t.Y += y;
            if( t.X < 0 || t.Y < 0 || t.X >= WID || t.Y >= HEI || !brd[t.X + WID * t.Y] ) return false;
        }
        return true;
    }
    bool existsMoves() {
        int i;
        for( int y = -1; y < 2; y++ ) {
            for( int x = -1; x < 2; x++ ) {
                if( !x && !y ) continue;
                i = brd[cursor.X + x + WID * ( cursor.Y + y )];
                if( i > 0 && countSteps( i, x, y ) ) return true;
            }
        }
        return false;
    }
    winConsole* console;
    int brd[WID * HEI];
    float score; coord cursor;
};
winConsole* winConsole::inst = 0;
int main( int argc, char* argv[] ) {
    srand( ( unsigned )time( 0 ) );
    SetConsoleTitle( "Greed" );
    greed g; g.play(); return 0;
}



Go: package main

import (
    "fmt"
    "github.com/nsf/termbox-go"
    "log"
    "math/rand"
    "strconv"
    "time"
)

type coord struct{ x, y int }

const (
    width  = 79
    height = 22
    nCount = float64(width * height)
)

var (
    board  [width * height]int
    score  = 0
    bold   = termbox.AttrBold
    cursor coord
)

var colors = [10]termbox.Attribute{
    termbox.ColorDefault,
    termbox.ColorWhite,
    termbox.ColorBlack | bold,
    termbox.ColorBlue | bold,
    termbox.ColorGreen | bold,
    termbox.ColorCyan | bold,
    termbox.ColorRed | bold,
    termbox.ColorMagenta | bold,
    termbox.ColorYellow | bold,
    termbox.ColorWhite | bold,
}

func printAt(x, y int, s string, fg, bg termbox.Attribute) {
    for _, r := range s {
        termbox.SetCell(x, y, r, fg, bg)
        x++
    }
}

func createBoard() {
    for y := 0; y < height; y++ {
        for x := 0; x < width; x++ {
            board[x+width*y] = rand.Intn(9) + 1
        }
    }
    cursor = coord{rand.Intn(width), rand.Intn(height)}
    board[cursor.x+width*cursor.y] = 0
    score = 0
    printScore()
}

func displayBoard() {
    termbox.SetCursor(0, 0)
    bg := colors[0]
    for y := 0; y < height; y++ {
        for x := 0; x < width; x++ {
            i := board[x+width*y]
            fg := colors[i]
            s := " "
            if i > 0 {
                s = strconv.Itoa(i)
            }
            printAt(x, y, s, fg, bg)
        }
    }
    fg := colors[9]
    termbox.SetCursor(cursor.x, cursor.y)
    printAt(cursor.x, cursor.y, "@", fg, bg)
    termbox.Flush()
}

func printScore() {
    termbox.SetCursor(0, 24)
    fg := colors[4]
    bg := termbox.ColorGreen
    s := fmt.Sprintf("      SCORE: %d : %.3f%%      ", score, float64(score)*100.0/nCount)
    printAt(0, 24, s, fg, bg)
    termbox.Flush()
}

func execute(x, y int) {
    i := board[cursor.x+x+width*(cursor.y+y)]
    if countSteps(i, x, y) {
        score += i
        for i != 0 {
            i--
            cursor.x += x
            cursor.y += y
            board[cursor.x+width*cursor.y] = 0
        }
    }
}

func countSteps(i, x, y int) bool {
    t := cursor
    for i != 0 {
        i--
        t.x += x
        t.y += y
        if t.x < 0 || t.y < 0 || t.x >= width || t.y >= height || board[t.x+width*t.y] == 0 {
            return false
        }
    }
    return true
}

func existsMoves() bool {
    for y := -1; y < 2; y++ {
        for x := -1; x < 2; x++ {
            if x == 0 && y == 0 {
                continue
            }
            ix := cursor.x + x + width*(cursor.y+y)
            i := 0
            if ix >= 0 && ix < len(board) {
                i = board[ix]
            }
            if i > 0 && countSteps(i, x, y) {
                return true
            }
        }
    }
    return false
}

func check(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

func main() {
    rand.Seed(time.Now().UnixNano())
    err := termbox.Init()
    check(err)
    defer termbox.Close()

    eventQueue := make(chan termbox.Event)
    go func() {
        for {
            eventQueue <- termbox.PollEvent()
        }
    }()

    for {
        termbox.HideCursor()
        createBoard()
        for {
            displayBoard()
            select {
            case ev := <-eventQueue:
                if ev.Type == termbox.EventKey {
                    switch ev.Ch {
                    case 'q', 'Q':
                        if cursor.x > 0 && cursor.y > 0 {
                            execute(-1, -1)
                        }
                    case 'w', 'W':
                        if cursor.y > 0 {
                            execute(0, -1)
                        }
                    case 'e', 'E':
                        if cursor.x < width-1 && cursor.y > 0 {
                            execute(1, -1)
                        }
                    case 'a', 'A':
                        if cursor.x > 0 {
                            execute(-1, 0)
                        }
                    case 'd', 'D':
                        if cursor.x < width-1 {
                            execute(1, 0)
                        }
                    case 'z', 'Z':
                        if cursor.x > 0 && cursor.y < height-1 {
                            execute(-1, 1)
                        }
                    case 'x', 'X':
                        if cursor.y < height-1 {
                            execute(0, 1)
                        }
                    case 'c', 'C':
                        if cursor.x < width-1 && cursor.y < height-1 {
                            execute(1, 1)
                        }
                    case 'l', 'L': 
                        return
                    }
                } else if ev.Type == termbox.EventResize {
                    termbox.Flush()
                }
            }
            printScore()
            if !existsMoves() {
                break
            }
        }
        displayBoard()
        fg := colors[7]
        bg := colors[0]
        printAt(19, 8, "+----------------------------------------+", fg, bg)
        printAt(19, 9, "|               GAME OVER                |", fg, bg)
        printAt(19, 10, "|            PLAY AGAIN(Y/N)?            |", fg, bg)
        printAt(19, 11, "+----------------------------------------+", fg, bg)
        termbox.SetCursor(48, 10)
        termbox.Flush()
        select {
        case ev := <-eventQueue:
            if ev.Type == termbox.EventKey {
                if ev.Ch == 'y' || ev.Ch == 'Y' {
                    break
                } else {
                    return
                }
            }
        }
    }
}