W 1 L 2 sh 1 C lessons LessonSubjectBook Week 1 lesson 1Objects, names Week 1 lesson 2Statements,...

24
W 1 L 2 sh 1 C lessons Lesson Subject Book Week 1 lesson 1 Objects, names Week 1 lesson 2 Statements, layout Week 2 lesson 1 Functions, decomposition Week 2 lesson 2 Lists, specification Week 3 lesson 1 Memory, testing Week 3 lesson 2 Fagan inspection

Transcript of W 1 L 2 sh 1 C lessons LessonSubjectBook Week 1 lesson 1Objects, names Week 1 lesson 2Statements,...

W 1 L 2 sh 1

C lessons

Lesson Subject Book

Week 1 lesson 1 Objects, names

Week 1 lesson 2 Statements, layout

Week 2 lesson 1 Functions, decomposition

Week 2 lesson 2 Lists, specification

Week 3 lesson 1 Memory, testing

Week 3 lesson 2 Fagan inspection

W 1 L 2 sh 2

How to make code readable

Names Names must help the reader to understand the code.

Format (layout) The layout must match the statement structure. The layout must be consistent.

Comments Comments must explain what the reader needs to know

but can not easily read from the code. Structure

The code must be structured to be understandable. Known concepts

Use concepts and techniques that are familiar (datastructures, patterns, real-world analogues).

W 1 L 2 sh 3

C statements

Declaration, definition Expression Compound : { . . . } Selection : if/else, switch/case/default/break Iteration : for, while, do/while, (break, continue) (labeled statement) – verboten!

W 1 L 2 sh 4

Indentation

Purpose : make reading easy (screen or print?). Consistency is probably more important than any

particular style. Save trees?

// Pascal - ANSI

if( a > b )

{

max = a;

}

else

{

max = b;

}

// Whitesmith if( a > b )

{

max = a;

n++;

}

else

{

max = b;

}

// K&R - 1TBS

if( a > b ){

max = a;

} else {

max = b;

}

if( a > b ){

max = a;

}

else {

max = b;

}

// Pico (compact)

if( a > b ){

max = a; }

else {

max = b; }

http://en.wikipedia.org/wiki/Indent_style

// Horstman

if( a > b )

{ max = a;

}

else {

max = b; }

W 1 L 2 sh 5

Selection - if

if( a > b ){

max = a;

}

if( a > b ){

max = a;

} else {

max = b;

}

if( a > b ){

max = a;

} else if ( b > a ){

max = b;

} else {

max = a;

equals++;

} If, if else, if … else Always use { } Write complex conditions

on multiple lines

if(

( x > 0 )

&& ( x < size_x())

&& ( y > 0 )

&& ( y < size_y())

){

VRAM_A[ x, y ] = color;

}

W 1 L 2 sh 6

Selection - switch

switch( c ){

case ’\n’ :

position.x = 0;

position.y= minimum( position.y + 1, 23 );

break;

case ’\v’ :

position.x = 0;

position.y = 0;

break;

default :

display[ position.x, position.y ] = c;

position.x = minimum( position.x + 1, 79 );

break;

}

Indent the cases as if there was a { } pair. Each case ends with a break.

W 1 L 2 sh 7

Iteration – while, do . . . while

int c;

while( EOF != ( c = getchar()) ){

putchar( convert_to_uppercase( c ));

}

Test before versus test afterwards. What is wrong with this do .. while loop?

int c;

do {

c = getchar();

putchar( convert_to_uppercase( c ));

} while( c != EOF );

W 1 L 2 sh 8

Iteration – for

int i, sum, values[ SIZE ];

. . .

sum = 0;

for( i = 0; i < SIZE; i++ ){

sum += values[ i ];

}

A for loop is just an easy notation for a while loop

i = 0;

while( i < SIZE ){

sum += values[ i ];

i++;

}

W 1 L 2 sh 9

Iteration – break

Break jumps to the statements after the loop(terminates the loop)

Use this: when a loop needs some ‘starting up’ before the condition can be checked. This is an idiom.

while( 1 ) {

c = getchar();

if( c == EOF ){

break;

}

putchar( convert_to_uppercase( c ));

chars_printed++;

}

W 1 L 2 sh 10

Iteration – continue

Continue jumps to the end of the statements in the loop (terminates this iteration)

Use this: seldom. Maybe when a very complex condition determines that the rest of the loop statements must be skipped.

while( 1 ) {

c = getchar();

if( c == EOF ){

break;

}

if( ! char_is_letter( c ){

continue;

}

putchar( convert_to_uppercase( c ));

chars_printed++;

}

W 1 L 2 sh 11

Condition

A condition is an integer expression. 0 is interpreted as ‘not true’. All other values are interpreted as ‘true’. Functions that return a condition must adhere to this

convention. Statements that check a condition must adhere to this

convention.

W 1 L 2 sh 12

Condition woes

if( strcmp( ”hello”, ”world” )){

printf( ”hello and world are equal” );

}

if( TRUE == isupper( ’A’ )){

printf( ”” );

}

Don’t write semi-predicate functions, or make the return type very very clear.

There is no representation for true.

W 1 L 2 sh 13

Reversi (Othello)

Black must place a piece with the black side up on the board, in such a position that there exists at least one straight (horizontal, vertical, or diagonal) occupied line between the new piece and another dark piece, with one or more contiguous white pieces between them.

After placing the piece, black turns over (flips) all white pieces lying on a straight line between the new piece and any anchoring black pieces.

http://en.wikipedia.org/wiki/Reversihttp://www.freegames.ws/games/boardgames/othello/othello.htm

W 1 L 2 sh 14

Reversi (Othello)

The opposing sides in turn place a piece on the board and chance the pieces on the board according to the rules.

When one side can not make a move it must pass.

When both sides must pass the black and white pieces are counted and the side having the most pieces wins.

Tactics include• Selecting good places first (borders, especially corners)• Maximizing the number of moves I can make• Minimizing the number moves my opponent can make• Minimizing (!) my number of stones

http://www.smartreversi.com/http://www.shareup.com/Deep_Green_Reversi-download-25622.html

W 1 L 2 sh 15

Reversi (Othello)

enum square {

border = 0,

empty = 1,

white = 2,

black = 3

};

typedef int board[ 100 ];

0 1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19

20 21 22 23 24 25 26 27 28 29

30 31 32 33 34 35 36 37 38 39

40 41 42 43 44 45 46 47 48 49

50 51 52 53 54 55 56 57 58 59

60 61 62 63 64 65 66 67 68 69

70 71 72 73 74 75 76 77 78 79

80 81 82 83 84 85 86 87 88 89

90 91 92 93 94 95 96 97 98 99

B B B B B B B B B B

B B

B B

B B

B w b B

B b w B

B B

B B

B B

B B B B B B B B B B

Starting positionSquare indexes in a board array

W 1 L 2 sh 16

Playing the game

W 1 L 2 sh 17

reversi.h

// initialize board b to the starting position

void reversi_board_init( board b );

// print the board b

void reversi_board_print( board b );

// copy the board s to the board d

void reversi_board_copy( board d, board s );

// convert a string "cn" to the index ( 0 .. 99 ) of the square.

// c must be a..h (or A..H), n must be 1..8.

// return -1 when the string is not valid

int reversi_move_from_string( char *s );

// return the number of squares that contain color

int reversi_board_count_color( board b, int color );

W 1 L 2 sh 18

reversi.h

// try to move a piece 'color' to the square move.

// return the number of opponent squares that would be flipped.

// return 0 if the move is not allowed (border, occupied)

// this function changes the board!

char reversi_flipped_board_color_move( board b, int color, int move );

// try to move a piece 'color' to the square move.

// return the number of opponent squares that would be flipped.

// consider only squares that lie in direction relative to the move.

// return 0 if the move is not allowed (border, occupied)

// this function changes the board!

char reversi_flipped_board_color_move_direction(

board b, int color, int move, int direction

);

// return the number of valid moves available for color

int reversi_board_n_moves( board b, int color );

W 1 L 2 sh 19

main.c – play gamevoid play_game( board b, int color ){

int passes = 0;

int count_black, count_white;

while( passes < 2 ){

if( play_move( b, color ) ){

passes = 0;

} else {

passes++;

}

color = ( color == white ? black : white );

}

count_white = reversi_flipped_board_count_color( b, white );

count_black = reversi_flipped_board_count_color( b, black );

printf( "game over!\n" );

printf( " black has %d pieces\n", count_black );

printf( " white has %d pieces\n", count_white );

if( count_white > count_black ){

printf( "white wins\n" );

} else if( count_black > count_white ){

printf( "black wins\n" );

} else {

printf( "it is a draw wins\n" );

}

}

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

board b;

reversi_board_init( b );

play_game( b, black );

}

W 1 L 2 sh 20

main.c – play moveint play_move( board b, int color ){

char s[132 ];

int move, flipped, allowed;

reversi_board_print( b );

for(;;){

allowed = reversi_board_n_moves( b, color );

printf(

"%s to move (%d moves allowed): ",

color == white ? "white (O)" : "black (X)",

allowed

);

if( allowed == 0 ){

printf( "\n so you will have to pass\n" );

return 0;

}

scanf( "%s", s );

move = reversi_move_from_string( s );

if( move == -1 ){

printf( "illegal format, please try again\n" );

continue;

}

flipped = reversi_flipped_board_color_move( b, color, move );

if( flipped == 0 ){

printf( "illegal move, please try again\n" );

continue;

}

return 1;

}

}

W 1 L 2 sh 21

Read

Book Chapter 6 Chapter 7

W 1 L 2 sh 22

Assignment

Write the missing code in reversi.c

Adhere to style guide!

Verify that you can play a game of reversi.

W 1 L 2 sh 23

Assignment

Function # Lines in my version

Remarks

reversi_board_init 18 Is provided

reversi_board_print 29 Lots of lines but basically very simple. Good place to start.

reversi_board_copy 6 Trivial

reversi_move_from_string 13 Lots of checks required, but basically simple.Test this one by itself (print the return value)

reversi_flipped_board_color_move_direction 29 This is the difficult part.

reversi_flipped_board_color_move 16 Calls reversi_flipped_board_color_move_direction for each direction. Is provided.

reversi_board_n_moves 11 Uses reversi_flipped_board_color_move. Trivial once you have that function. Do not forget to copy the board before each call!

reversi_board_count_color 9 Trivial

W 1 L 2 sh 24

Assignment – hints

If the square is not empty, the move is illigal. Walk in the indicated direction

Border or empty return 0 Enemy piece continue walking My own piece stop walking

Now walk back Enemy piece flip it Back at the square return # flipped enemies

// try to move a piece 'color' to the square move.

// return the number of opponent squares that would be flipped.

// consider only squares that lie in direction relative to the move.

// return 0 if the move is not allowed (border, occupied)

// this function changes the board!

char reversi_flipped_board_color_move_direction(

board b, int color, int move, int direction

);