Is this text readable?CS109 Programming ProjectsThe Mastermind gameLCD display and clock

LCD display and clock

Many LED or LCD displays consist of seven segments. By turning these segments on in different ways, we can display the digits from 0 to 9:
 ###         ###   ###         ###   ###   ###   ###   ### 
#   #     #     #     # #   # #     #         # #   # #   #
#   #     #     #     # #   # #     #         # #   # #   #
#   #     #     #     # #   # #     #         # #   # #   #
             ###   ###   ###   ###   ###         ###   ### 
#   #     # #         #     #     # #   #     # #   #     #
#   #     # #         #     #     # #   #     # #   #     #
#   #     # #         #     #     # #   #     # #   #     #
 ###         ###   ###         ###   ###         ###   ### 

In this project we want to implement a clock that displays the time in LCD-format.

We will build up the project in small steps, one function at a time.

lcdDigit

Let us number the seven segments from 0 to 6 as follows:

  555  
 4   0 
 4   0 
 4   0 
  666  
 3   1 
 3   1 
 3   1 
  222  

I have made a table which tells us which segment to turn on for each digit:

val digits = 
  listOf(listOf(true, true, true, true, true, true, false),     // 0
	listOf(true, true, false, false, false, false, false),  // 1
	listOf(true, false, true, true, false, true, true),     // 2
	listOf(true, true, true, false, false, true, true),     // 3
	listOf(true, true, false, false, true, false, true),    // 4
	listOf(false, true, true, false, true, true, true),     // 5
	listOf(false, true, true, true, true, true, true),      // 6
	listOf(true, true, false, false, false, true, false),   // 7
	listOf(true, true, true, true, true, true, true),       // 8
	listOf(true, true, true, false, true, true, true),      // 9
	listOf(false, false, false, false, false, false, false)) // Blank
For example, digits(5) is a list of 7 Boolean's, telling us to switch on segments 1, 2, 4, 5, 6. Note the entry with index 10, which simply displays a blank.

Your first task is to write a function

fun lcdDigit(digit: Char, k: Int, c: Char): String {
  // ...
}
This function takes a character digit and returns a string that represents this character in LCD-format. k is the size of the LCD-display, c is the character to be used for the LCD-display.

When digit is not a digit, the function should simply return a blank string. You can use the following code to convert digit to an index for the digits table:

  val d = if ('0' <= digit && digit <= '9') digit - '0' else 10

Here are some examples for the output:

$ ktc
Welcome to Kotlin version 1.0.1-2 (JRE 1.7.0_101-b00)
Type :help for help, :quit for quit
>>> :load lcd1.kts
>>> lcdDigit('0', 2, '*')
 ** 
*  *
*  *
    
*  *
*  *
 ** 
>>> lcdDigit('4', 3, '&')
     
&   &
&   &
&   &
 &&& 
    &
    &
    &
     
>>> lcdDigit('9', 5, 'M')
 MMMMM 
M     M
M     M
M     M
M     M
M     M
 MMMMM 
      M
      M
      M
      M
      M
 MMMMM 
>>> lcdDigit('a', 3, 'M')
     
     
     
     
     
     
     
     
     
Note that the character 'a' is simply displayed as a blank.

Note that the function does not print the digit itself. It only returns a string. Since this string goes over several lines, it needs to contain the "new-line" character, which you can enter as \n. There should be no new-line character at the beginning and at the end of the output string.

Combine

Next we need a function that combines two digits:

fun combine(left: String, sep: String, right: String): String {
  // ...
}

This function needs to split both left and right into pieces at the new-line characters. It then adds the pieces together, and finally generates a new string.

You can use s.split("\n") to split a string into a list of strings, and r.joinToString(separator = "\n") to compose a list of strings into a single long string.

Here are some examples:

>>> combine("This\nis\nfun", "&", "Hello\nCS109\nStudents!")
This&Hello
is&CS109
fun&Students!
>>> combine(lcdDigit('0', 3, '*'), " # ", lcdDigit('9', 3, '@'))
 ***  #  @@@ 
*   * # @   @
*   * # @   @
*   * # @   @
      #  @@@ 
*   * #     @
*   * #     @
*   * #     @
 ***  #  @@@ 

lcd

Next, we need a function that takes a string and changes it to LCD-format. To save you some typing, here it is:

fun lcd(s: String, k: Int, c: Char, sep: String): String {
  var result = lcdDigit(s[0], k, c)
  for (i in 1 until s.length)
    result = combine(result, sep, lcdDigit(s[i], k, c))
  return result
}

Test the function and check that it works well:

 
>>> lcd("12:45:99", 4, '@', ":")
      : @@@@ :      :      : @@@@ :      : @@@@ : @@@@ 
     @:     @:      :@    @:@     :      :@    @:@    @
     @:     @:      :@    @:@     :      :@    @:@    @
     @:     @:      :@    @:@     :      :@    @:@    @
     @:     @:      :@    @:@     :      :@    @:@    @
      : @@@@ :      : @@@@ : @@@@ :      : @@@@ : @@@@ 
     @:@     :      :     @:     @:      :     @:     @
     @:@     :      :     @:     @:      :     @:     @
     @:@     :      :     @:     @:      :     @:     @
     @:@     :      :     @:     @:      :     @:     @
      : @@@@ :      :      : @@@@ :      : @@@@ : @@@@ 

A real clock

If you got the lcd-function working, there is nothing to stop us from implementing our clock. Since it's mostly special functions for obtaining and formatting the current time, I wrote it for you:

fun clearScreen() {
  println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n")
}

fun clock() {
  val form = java.text.SimpleDateFormat("HH mm ss")
  var current = form.format(java.util.Calendar.getInstance().getTime())
  clearScreen()
  println(lcd(current, 4, '#', " "))
  while (true) {
    Thread.sleep(100)
    val ntime = form.format(java.util.Calendar.getInstance().getTime())
    if (ntime != current) {
      current = ntime
      clearScreen()
      println(lcd(current, 4, '#', " "))
    }
  }
}

Note that it runs forever. You can stop it by typing Ctrl+C.

Is this text readable?CS109 Programming ProjectsThe Mastermind gameLCD display and clock